3 puntos por GN⁺ 2023-07-19 | 1 comentarios | Compartir por WhatsApp
  • Hylo apunta a la programación segura de sistemas y genérica con base en semántica de valores; aunque el compilador y la biblioteca estándar aún están en una etapa inicial, se pueden ejecutar ejemplos en Compiler Explorer
  • La investigación del lenguaje se centra en temas como la extensión de inout projection para subscript de Swift, method bundles, concurrencia estructurada y listas doblemente enlazadas basadas en semántica de valores
  • El compilador usa LLVM y también aborda compilación genérica con coherence, caché y serialización del estado del programa, e investigación sobre interoperabilidad con C
  • El entorno de desarrollo ofrece extensión para VSCode, compilador de documentación y un prototipo de Language Server, con soporte para SPM/CMake, Ninja/Xcode, Windows/Linux/macOS e imágenes Docker del toolchain de desarrollo
  • Los ejemplos muestran reglas de propiedad y liberación a nivel de código mediante projection segura y sink method, ilustrando cómo un lenguaje de sistemas puede imponer seguridad

Alcance y estado actual de Hylo

  • El compilador y la biblioteca estándar de Hylo aún están en una etapa inicial
  • Se pueden ejecutar ejemplos de código avanzado de Hylo en Compiler Explorer
  • También se ofrece un enlace para probar Hylo en Compiler Explorer desde la pantalla principal

Semántica de valores e investigación del lenguaje

Compilador y biblioteca estándar

  • El trabajo del compilador abarca compilación basada en LLVM, genéricos, persistencia de estado e interoperabilidad con C
    • Compilación con LLVM
    • Nueva técnica para compilación genérica con coherence
    • Caché y serialización del estado del programa en el compilador
    • Investigación sobre C interop
  • En la biblioteca estándar, actualmente se publican documentación de la implementación y trabajos relacionados con algoritmos de colecciones

Experiencia de desarrollador y entorno de compilación

  • También se ofrecen herramientas para editor, documentación y servidor de lenguaje
  • El entorno de compilación y desarrollo soporta varios sistemas operativos y flujos basados en contenedores
    • Soporte para Development Containers para reducir los pasos de inicio
    • Soporte para SPM/CMake, Ninja/Xcode, Windows/Linux/macOS
    • Plugin de compilador para generación de pruebas
    • Imagen Docker precompilada del Hylo development toolchain
    • El compilador está escrito en Swift 6.2

Investigación y materiales de presentación sobre Hylo

Ejemplos de código: projection segura y liberación explícita

  • El ejemplo Subscripts - A Safe Projection Mechanism muestra una estructura donde el tipo Angle almacena el valor radians y expone la propiedad degrees mediante bloques let e inout
    • El bloque let de degrees convierte radians a degrees y lo devuelve
    • inout expone un valor temporal en degrees d con yield &d y luego vuelve a convertir el valor modificado a radians para reflejarlo en self.radians
    • main obtiene una projection con inout d = &a.degrees, cambia d a 0.0 y luego verifica que a.radians == 0.0
  • El ejemplo Sink Methods - Capability for Deinitializing muestra una estructura donde el tipo Computer provee shutdown() como sink method
    • shutdown() imprime el contenido de la memoria y luego aplica sink a self.ram
    • En test1, se crea un Computer y no se hace shutdown, por lo que ocurre Cannot deinit computer
    • En test2, como shutdown solo se ejecuta dentro de if random_bool(), en la ruta donde no se entra al if ocurre Cannot deinit computer
    • En test3, si se llama a shutdown dentro de while, después de la primera iteración aparece un problema por usar un objeto ya consumido, y en la ruta donde no se entra al while sigue quedando la imposibilidad de deinit
  • Se pueden revisar ejemplos adicionales en la compiler test suite

1 comentarios

 
GN⁺ 2023-07-19
Opiniones de Hacker News
  • Como sucesor de C++, quizá Val me entusiasme más que el excelente CppFront de Herb Sutter. Solo vi las dos charlas de abajo, pero sus puntos clave parecen ser compilación estática, tipado estático, interoperabilidad con C++, seguridad de memoria, seguridad de tipos y ausencia de carreras de datos.
    Cuando lo explico, digo algo como: “Supongamos que empiezas un nuevo proyecto en C++ y, dejando de lado el rendimiento, pasas todo por valor y devuelves todo por valor, sin punteros ni referencias; sería bueno no tener que preocuparse por efectos secundarios ni carreras de datos”. Lo interesante de Val es que, aunque el lenguaje elimine los punteros y las referencias, el compilador internamente aplica paso por referencia const y optimización de valores de retorno, de modo que conserva al mismo tiempo la semántica deseada y el rendimiento.
    Val: A Safe Language to Interoperate with C++ - Dimitri Racordon - CppCon 2022 https://www.youtube.com/watch?v=ws-Z8xKbP4w
    https://cppcast.com/val-and-mutable-value-semantics/

    • Conviene escuchar los dos episodios recientes del ADSP Podcast en los que Sean Parent habla de Val. Adobe Research Labs está patrocinando su desarrollo con bastante seriedad.
      https://adspthepodcast.com/
    • Lo de “interoperar con C++” me genera dudas. Cuesta creer que otro lenguaje pueda interoperar correctamente con C++; incluso entre compiladores de C++ se rompe la compatibilidad binaria, y a veces también entre versiones del mismo compilador.
    • Suena a una arquitectura que confía demasiado en el compilador. Me preocupa que un cambio pequeño pueda romper una optimización en código lejano y arruinar el rendimiento.
    • Si “pasas por valor y devuelves por valor todo el día”, ya no es fácil modificar o almacenar referencias eficientemente dentro de estructuras. Si el programa necesita aunque sea una estructura de datos un poco no estándar o compleja, parece una restricción fatal. Claro que, si pensamos en lo difícil que es implementar correctamente esas estructuras, tal vez sea más bien una ventaja.
    • Durante años escribí programas PHP reales de esta manera, pasando arrays por todos lados sin preocuparme.
      Creo que el intérprete de PHP es lo bastante inteligente como para usar copia en escritura (copy-on-write) en la práctica, aunque nunca lo perfilé directamente. Aun así, no noté problemas de rendimiento perceptibles, incluso haciendo en cada carga de página procesamiento de datos bastante complejo, parsing de DSL carácter por carácter, generación dinámica de SQL y masajeo de resultados en estructuras arbitrarias.
      En la época de PHP 4, los objetos también se comportaban como valores almacenados en variables; cuando luego cambiaron las variables de objeto a semántica de referencia, creo que fue una oportunidad perdida no convertir “valor, referencia a variable, puntero a valor” en atributos de variable ortogonales al tipo almacenado.
      $a = $b; // copia el valor de $b en $a
      $a = &$b; // $a y $b ahora son la misma variable
      $a = *$b; // $a apunta al mismo objeto que $b, pero a diferencia de $a = &$b, las variables en sí no quedan vinculadas
  • Por un lado, es bueno que estén apareciendo tantos lenguajes de abstracción sin costo, pero también me gustaría que los programadores de sistemas ya eligieran un ganador. Ojalá la ya pequeña comunidad de programadores de sistemas no se fragmente aún más entre Rust, Zig, Val, etc., y que la guerra de lenguajes de sistemas termine pronto.

    • Quizá elegimos uno demasiado pronto y por eso durante demasiado tiempo faltó innovación en este campo. Bienvenida sea la guerra.
    • A estas alturas, creo que el ganador es Rust. Ya superó la enorme barrera de entrar de verdad en los kernels de Linux y Windows. En ese sentido, no parece quedar mucho espacio para que entre otro lenguaje de sistemas nuevo.
    • No creo que vaya a ser así. Por eso mismo hay todavía más razones para ampliar el soporte de wasm + wasi en todas partes.
  • Hoy conocí Val por primera vez, y mi secuencia de emociones fue esta: “Oh, un nuevo lenguaje de sistemas. Puede que no sea gran cosa, pero veamos. La documentación está bien. Las ideas sobre ownership son bastante consideradas y la sintaxis tiene sentido. Pero ¿es lo bastante distinto como para justificar su propia existencia? ¿Quién lo está haciendo?”
    Entonces vi que Dave Abrahams está trabajando en él y me interesó más. Me lo crucé en Apple y recuerdo su charla Crusty sobre Swift[1]. Me gustaban sus opiniones fuertes, pero Apple luego bajó ese video porque contenía consejos antiguos. Ahora está en Adobe, así que me pregunto si este será un lenguaje de Adobe.
    Mi conclusión es que vale la pena seguirlo, ver la charla enlazada y esperar.
    [1] Encontré la charla Crusty: "I don't do Object Oriented!" https://www.youtube.com/watch?v=p3zo4ptMBiQ

    • David Abrahams ya era un colaborador muy importante de Boost antes de estar en Apple, además de miembro del comité de C++ y un firme defensor de la programación genérica al estilo Stepanov. No sorprende que se haya sumado al proyecto Val.
  • Como desarrollador de compiladores, me impactó ver estos issues
    https://github.com/val-lang/val/issues/758
    https://github.com/val-lang/val/issues/711
    Huele a que el estado de la implementación no es bueno. Deberían llegar al self-hosting lo antes posible, y entonces encontrarán más de estos bugs básicos. Aun así tiene más de 500 estrellas

    • Visto como otro desarrollador de compiladores, hay pocos errores tan dañinos como hacer self-hosting demasiado pronto. Aunque el lenguaje sea una ganancia neta para programas pequeños y medianos, toma mucho más tiempo que sea adecuado para un proyecto grande como un compilador y que además tenga buenas herramientas. Me alegra que no se estén apurando
    • Si esos bugs estuvieran en un compilador en producción, sería preocupante, pero si es el compilador de un lenguaje que todavía se está definiendo, no es tan grave. Si comparas Rust 1.0 y 1.71, se ve cuán grande es la brecha entre “primer release estable” y “compilador de un lenguaje estable con mucho uso real”
      El self-hosting tampoco lo es todo. Más que nada es un hito simbólico, y cuando se logra es algo para celebrar, pero no creo que deba considerarse una debilidad del lenguaje hasta mucho más adelante en el ciclo de desarrollo
    • Swift mismo todavía no hace self-hosting y está por lanzar la versión 6. No soy desarrollador de compiladores, pero en la comunidad de Swift la conclusión de las discusiones sobre este tema fue que todavía no vale la pena
  • Desde hace tiempo venía posponiendo “jugar con Val” y hoy por fin lo intenté, pero aunque tiene más de 4,000 commits, todavía está lejos de ser usable. La mayoría de los ejemplos del tour del lenguaje no compilan, e incluso ejemplos que a simple vista parecen simples fallan
    Carbon todavía no ha presentado nada sólido, y Sean Baxter está avanzando mucho con el compilador Circle e implementando también varias de las partes buenas de Carbon. Si todavía es difícil considerarlo un lenguaje, también es difícil que sea un sucesor

  • Ahora existen V, Val, Vala y Vale. ¿Hay algún otro lenguaje que esté olvidando?

    • También existe VAL. Es uno de los lenguajes de los 80 e influyó en Haskell a través de SISAL. Aunque probablemente no mucha gente conozca ese VAL fuera de la comunidad de lenguajes paralelos
    • Un nombre parecido incluso puede jugar a favor. Quien aprende un lenguaje así probablemente está buscando “la nueva cosa de moda”, y puede enterarse de otros lenguajes con nombres parecidos y ponerse a investigarlos. Con JavaScript también pasó eso, y el resultado no fue tan malo
    • De verdad pensé que esto era Vale. Es una lástima el choque de nombres
    • Además, a V también se le dice Vlang, y Vale antes también se llamaba Vlang
  • Es un comentario que aparece siempre, pero lo único que no me gusta de Val es que Vale y V también sean nuevos lenguajes de sistemas. Por los nombres, es demasiado fácil confundir los tres

    • También existe Vala. El ámbito es algo distinto, pero es otro lenguaje con un nombre parecido
    • Tuve que entrar al enlace para comprobar si era el lenguaje de proyecciones o el lenguaje de regiones
    • También existe VAL: Variable Assembly Language https://en.m.wikipedia.org/wiki/Variable_Assembly_Language
  • Hay una publicación relacionada. ¿Hay más?
    Val, a new programing language inspired by Swift and Rust - https://news.ycombinator.com/item?id=31788527 - junio de 2022, 19 comentarios

  • Le eché un vistazo al paper sobre “mutable value semantics”, y me pregunto si entiendo bien que los autores proponen reemplazar referencias y punteros por a) cierta indirección y chequeos en runtime mediante structs anidados y Any, y b) índices de arreglos
    Me llamó la atención el pasaje: “Es válido preguntar cómo se pueden expresar estructuras de datos autorreferenciales como listas doblemente enlazadas o grafos dirigidos con tipos de valor mutables. De hecho, cualquier grafo arbitrario se puede representar como una lista de adyacencia…”. No veo bien cómo implementar razonablemente una lista doblemente enlazada sin volver a crear dentro de la implementación un heap de memoria y una especie de garbage collection
    Además encontré una discusión en https://github.com/orgs/val-lang/discussions/736, y parece que habrá una vía de escape similar a unsafe de Rust. Eso resuelve todos los problemas, pero la pregunta de si “el subconjunto seguro de Val por sí solo basta para crear aplicaciones prácticas” probablemente seguirá siendo motivo de debate por mucho tiempo

    • Si usas un arreglo y índices de arreglos en lugar de punteros, efectivamente puedes recrear la memoria
      La razón por la que esto es menos tonto de lo que parece es que esos índices están ligados a una estructura de datos específica, por ejemplo una lista doblemente enlazada o un grafo, así que no es fácil manipularlos para acceder a otra parte del programa. Eso aplica tanto cuando el compilador lo verifica como ante intentos de romper el programa
  • No sé cómo debería leerse la explicación del ejemplo de la página principal. Dice: “No se producen asignaciones innecesarias. Como el resultado de longer_of es una proyección del argumento más largo, si emphasize modifica z, el cambio se aplica directamente al valor de y. El valor no se copia ni se mueve, pero tampoco se pasa por referencia a emphasize”.
    Se trata de una situación en la que se pasa un argumento de cadena a una función y se le agrega un carácter, pero la cadena existente debía tener una longitud inicial y una ubicación y tamaño concretos en la pila; no entiendo cómo puede ser posible sin una nueva copia de y. ¿Acaso dejan padding extra al final de la cadena por si alguien le agrega algo? Si es así, ¿cuánto padding dejan y por qué no resulta más ineficiente en general?

    • El prefijo de cuatro espacios no es para citar, sino para bloques de código/ancho fijo. En HN normalmente se usa la convención > para citar, y funciona bien aunque el parser no le dé un tratamiento especial.
    • Que sea un valor inmutable no significa necesariamente que tenga que estar en la pila.
      Pero tengo una duda parecida. ¿Qué pasa si se modifica una cadena de 1 GB? ¿Es copy-on-write?
      En el 99% de los casos quizá pueda desaparecer con optimizaciones, pero me da la sensación de que en el 1% restante podría aparecer una degradación de rendimiento muy difícil de encontrar.
    • Respondiéndome a mí mismo unos días después: parece posible si se hace shadowing discretamente en la pila del nombre de la variable modificada con un nuevo valor más largo. Tal vez eso sea lo que significa “projection”. En ese caso, como la pila ya está asignada, no se produce una nueva asignación. No soy experto en lenguajes ni compiladores, así que quizá ese término sea muy conocido en ese ámbito.
    • Hay más explicación más abajo. longer_of no es una función, sino un subscript, y dicen que un subscript no devuelve un valor, sino que proyecta un valor y concede al llamador acceso temporal de lectura/escritura.
      No entiendo bien por qué eso no cuenta como un movimiento. En el caso de las cadenas, también podrían ponerlas en el heap, como Rust, para permitir tamaño variable.