1 puntos por GN⁺ 2026-04-25 | 1 comentarios | Compartir por WhatsApp
  • Compilador AOT que convierte código fuente Ruby a código C mediante inferencia de tipos de programa completo y genera binarios nativos independientes
  • Desarrollado directamente por matz, creador de Ruby; el propio backend del compilador está escrito en Ruby y tiene una arquitectura self-hosting que se compila a sí misma
  • Rendimiento aprox. 11.6 veces más rápido que miniruby (Ruby 4.1.0dev); Conway's Game of Life mejora 86.7 veces, ackermann 74.8 veces y mandelbrot 58.1 veces
  • El pipeline de compilación usa un parser basado en Prism para convertir Ruby en texto AST, después el backend self-hosting realiza la inferencia de tipos y la generación de código C, y finalmente crea un binario standalone con un compilador C estándar
  • Soporta una amplia gama de funciones de Ruby, incluyendo clases, herencia, bloques, manejo de excepciones, Fiber, motor Regexp NFA integrado, Bigint con promoción automática, pattern matching y más
  • Las clases pequeñas con 8 campos escalares o menos se asignan automáticamente en la pila como value types, eliminando por completo el overhead del GC (1 millón de asignaciones: 85 ms → 2 ms)
  • Aplana el encadenamiento de strings a + b + c + d en una sola llamada a malloc; en bucles, split reutiliza sp_StrArray para eliminar asignaciones innecesarias
  • Incluye múltiples optimizaciones en tiempo de compilación, como hoisting de longitud invariante en bucles, propagación de constantes, inlining automático de métodos de 3 sentencias o menos y terminación anticipada de inferencia iterativa (~14% menos tiempo de bootstrap)
  • Los binarios generados tienen cero dependencias de runtime y pueden ejecutarse solo con libc + libm
  • No soporta eval, metaprogramación, ni Thread o Mutex (solo Fiber)
  • Licencia MIT

1 comentarios

 
GN⁺ 2026-04-25
Comentarios en Hacker News
  • Si lo hizo Matz, entonces seguramente conoce bien incluso las limitaciones de la semántica de Ruby, así que inspira confianza
    Mi tesis de maestría también fue sobre un compilador AOT de JS; sí funcionaba, pero las restricciones sobre los datos de entrada eran tan grandes que al final la abandoné
    En ese tiempo los desarrolladores de JS no estaban tan acostumbrados a imponerse esas restricciones por su cuenta, y entradas intrínsecamente incognoscibles como JSON.parse eran un obstáculo
    Ahora, gracias a TypeScript, podría ser mucho más viable que en ese entonces
    Incluso viendo el cálculo lambda general, los límites de la inferencia de tipos son claros, y se ven restricciones similares en los papers de Matt Might o en el trabajo de Shed-skin para Python
    Me da curiosidad qué tan comunes son eval, send, method_missing y define_method en código Ruby real, y también cómo suelen manejar entradas sin tipo, por ejemplo datos JSON

    • Este diseño se ve bastante pragmático
      Parsear Ruby es casi más difícil que la propia traducción, así que usan Prism, y el resultado genera C
      Implementar la semántica básica de Ruby en sí no es tan difícil
      En cambio, yo sigo batallando con un viejo compilador AOT self-hosting hecho en Ruby puro, y por insistir en usar su propio parser tomé a propósito un camino mucho más difícil
      Aprendí temprano que el primer 80% se puede hacer más o menos y aun así lograr que corra una buena parte del código Ruby; el verdadero “segundo 80%” difícil está concentrado en las cosas que Matz dejó fuera de este proyecto y de mruby, como la codificación y toda clase de funciones periféricas
      Si soy honesto, Ruby también tiene varias funciones que nunca he visto una sola vez en código real, así que no me sorprendería que algunas quedaran deprecated
      send, method_missing y define_method son muy comunes
      Las restricciones son parecidas a las de mruby, y aun bajo esas restricciones sí hay casos de uso
      El soporte para send, method_missing y define_method es relativamente fácil
      En cambio, dar soporte a eval() es una pesadilla
      Aun así, una gran parte del uso de eval() en Ruby puede reducirse estáticamente a la versión con bloque de instance_eval, y en esos casos la compilación AOT se vuelve bastante sencilla
      Por ejemplo, si la cadena que entra a eval() se puede conocer o descomponer estáticamente, hay bastante margen para resolverlo
      De hecho, mucho uso de eval() es innecesario o se parece más a rodeos simples para introspección, así que puede tratarse con análisis estático
      En mi compilador también pienso empezar por ahí si eso se vuelve el cuello de botella
    • Se necesitan bastantes funciones así para crear la magia al estilo Rails
      La ingestión de JSON sin tipos probablemente también use mecanismos así
      Si quitas eso, queda un lenguaje pequeño y fácil de leer que no es tan fuertemente tipado como Crystal, pero tampoco depende tanto de la metaprogramación como Ruby oficial
      Por eso parece tener bastante potencial, pero al final habrá que ver con el tiempo
    • Si compila Ruby a Objective-C, parecería posible soportar todas las funciones de Ruby y aun así ser más rápido que Ruby interpretado
    • Yo sí uso eval con frecuencia
      Podría no usarlo, pero para mí así es más ergonómico
    • En mi experiencia, lo interesante es eval, exec, define_method y también el patrón de crear clases nuevas con Class.new y Struct.new
      La mayoría de esos usos se concentra en el arranque de la app o mientras se hace require de archivos, y en cierto sentido eso ya se parece a una etapa de compilación
  • Esto es lo que Matz acaba de presentar en RubyKaigi 2026
    Es experimental, pero lo hizo en alrededor de un mes con ayuda de Claude, y la demo en vivo también salió bien
    El nombre viene del nuevo gato de Matz, y el nombre del gato viene del gato de Card Captor Sakura, donde además hace pareja con un personaje llamado Ruby

    • La gente habla mucho de IA que escribe programas enteros de principio a fin, pero creo que un escenario más realista es que convierta a un programador 10x en un programador 100x
      En alguien como Matz, eso podría significar empujarlo de 100x a 500x
    • La referencia más reciente que tengo de Spinel es la de Steven Universe, así que no entendí para nada el juego de palabras Spinel/Ruby (Moon), pero ahora que lo sé me alegró el día
    • Yo naturalmente pensé que hablaban del mineral spinel :)
      https://en.wikipedia.org/wiki/Spinel
    • Gracias
      Parece que el video todavía no está en vivo, y da la impresión de que los van subiendo uno por uno a este canal
      https://www.youtube.com/@rubykaigi4884/videos
    • La historia del origen del nombre del gato se ve bastante sospechosa si se piensa en el drama de Ruby Central y la relación con los fundadores de Spinel.coop
      También da la impresión de que el nombre del proyecto se eligió de forma emocional
  • Sin duda es súper impresionante, pero parece imposible de mantener sin un agente de IA
    spinel_codegen.rb tiene 21 mil líneas, y algunos métodos llegan a 15 niveles de anidación
    El código de compiladores rara vez es bonito de por sí, pero incluso con ese estándar esto se ve muy difícil de mantener para una persona

    • El código de compiladores sí puede quedar bonito si se le dedica tiempo
      Los compiladores tienen límites entre subsistemas muy claros y handoffs bien definidos entre etapas, así que en realidad están entre las cosas más fáciles de hacer de forma modular
      El problema casi siempre es que primero se hace que funcione y luego ya no queda tiempo para refactorizar, y entonces el desorden sigue creciendo
    • spinel_codegen.rb está casi al nivel de horror eldritch
      Cuando uso Claude, a mí también siempre me sale este tipo de código espagueti, y pensé que tal vez yo estaba haciendo algo mal
      Pero ver que incluso en un proyecto realmente interesante hecho por alguien a quien considero un programador de primer nivel la calidad del código es bastante mala en varias partes me hizo ver que no me pasa solo a mí
      Por ejemplo, infer_comparison_type() ni siquiera es el peor caso ni es ilegible, pero existe una implementación mucho más simple y clara y aun así Claude no llega ahí
      Si agrupas los operadores de comparación en un Set y lo manejas con include?, queda más corto, más rápido, más legible y más fácil de mantener
      Pero Claude siempre termina cayendo en cadenas de if-return, e incluso da la impresión de que hasta los if-else le resultan ajenos
      Mi codebase hecho con Claude también está lleno de ese patrón, así que ahora sé que no me pasa solo a mí
      En cambio, otros archivos están bastante mejor, y en especial el directorio lib parece corresponder al directorio ext del repo principal de Ruby y tiene una calidad decente
      La API también está claramente influida por MRI Ruby, y aunque la implementación sea bastante distinta, parece que Matz guio el resultado para que se pareciera a parte de la API original y así quedara más ordenado
      [1] https://github.com/matz/spinel/blob/98d1179670e4d6486bbd1547...
    • En esta etapa no creo que sea tan importante si una persona puede mantenerlo a mano
      Si pasa las pruebas y los benchmarks, por ahora me doy por satisfecho
      Aun así, sí me pregunto si un archivo gigante también es fácil de manejar para la IA
      Yo intento limitar los archivos a menos de 300 líneas, y creo que el código fácil de entender para humanos también lo será para los agentes de programación
  • Dicen que las restricciones son estas
    No eval: eval, instance_eval, class_eval
    No metaprogramming: send, method_missing, define_method (dinámico)
    No threads: Thread, Mutex (sí soporta Fiber)
    No encoding: asume UTF-8/ASCII
    No general lambda calculus: -> x { } profundamente anidado con llamadas []
    En lo personal, asumir UTF-8/ASCII no me parece una restricción tan grave, pero el resto sí parece una limitación real para bastantes programas
    Y volver a meter todo eso parece que requeriría bastante trabajo

    • Con eso desaparece buena parte de la magia de Ruby
  • Llevo mucho tiempo usando Ruby, y habiendo usado todas las funciones listadas, siento que al final de mi propia evolución justo terminé queriendo esta versión de Ruby simple
    Es más simple y más fácil de entender, pero todavía conserva la estética propia de Ruby
    Ahora, gracias a los LLM, la productividad para generar código es tan alta que ya no hace tanta falta reducir boilerplate con metaprogramación para mejorar la productividad del desarrollador como antes
    Porque cada vez escribimos menos código directamente

    • Si lo que quieres es solo la estética de Ruby, Crystal también podría encajar bien
      La sintaxis es parecida y tiene un sistema de tipos estático, lo que lleva a código compilado más eficiente
    • Que no haya eval hasta me parece mejor, pero que tampoco haya threads ni mutexes sí me decepciona
      La ausencia de define_method se entiende por su caso de uso
      Pero send y method_missing son comunes en librerías existentes, y tampoco parecería tan difícil implementarlos construyendo en compilación una tabla de lookup en memoria
      Así que no sé si lo dejaron fuera a propósito o si simplemente todavía no han llegado hasta ahí
      Espero que sea lo segundo, pero al menos por ahora, por compatibilidad, parece difícil usarlo en producción
    • La ventaja de la metaprogramación nunca fue originalmente escribir menos código
      Fue reducir la cantidad de código que hay que leer
  • Esto está buenísimo, y yo llevaba mucho tiempo esperando un compilador AOT para Ruby
    Sí da lástima que no haya fallback para eval o metaprogramación, aunque parece que eligieron eso para concentrarse en un subconjunto pequeño y de alto rendimiento
    Ojalá los gems construidos con este compilador AOT interactúen bien con MRI
    Para empaquetar o bundlear Ruby estándar y gems todavía hacen falta tebako, kompo u ocran, y antes también existían proyectos como ruby-packer, traveling ruby y jruby warbler
    Está bien tener una opción más, pero sigo esperando una versión definitiva con una mejor UX para desarrolladores

    • Sí, yo también hace poco tuve que hacer fork de warbler
      Porque llevaba demasiado tiempo sin actualizarse
  • Me pregunto por qué no threads
    El scheduler de Ruby y la implementación subyacente con pthread parecerían funcionar bien también en el mundo de C, así que me pregunto si apuntan a zero dependency
    Si no piensan agregarlo más adelante como extensión opcional, o si no es simplemente que todavía no lo implementan, esta decisión sí se siente un poco rara

    • Aún no he visto evidencia de que hayan decidido no soportarlo de forma deliberada
      Más bien sospecho que simplemente todavía no han llegado hasta ahí
      El multithreading siempre ha sido muy difícil de hacer bien
  • Sorprende que lo hayan hecho en poco más de un mes
    Se diga lo que se diga sobre la IA, en manos de desarrolladores con habilidad produce una aceleración enorme

    • Toda la industria arranca instalando agent harness, SOUL.md, permisos, skills, MCPs, hooks y env
      Matz en cambio parece sentir que con gem env|info y find ya basta
  • Siendo algo hecho por Matz, me pregunto qué tan realista es que en el futuro pase a ser parte de Ruby core
    Y si eso ocurriera, también me pregunto qué tanto amenazaría a Crystal

    • Crystal tiene un sistema de tipos estático explícito y está optimizado a nivel de lenguaje para compilación AOT
      Esas características son prácticamente indispensables para compilar y mantener programas grandes
      En cambio, esto es un subconjunto limitado de Ruby, así que la mayoría de los gems populares de Ruby no van a funcionar tal cual
      Como subconjunto de lenguaje orientado a compilar a C, se parece más a PreScheme
      En este punto no creo que ambos compitan directamente en el mismo espacio
      Ruby completo casi con seguridad necesita JIT
      [1]: https://prescheme.org/
    • Visto desde otro ángulo, parece que eventualmente los LLM van a llegar al punto de producir una especificación formal en cualquier lenguaje que queramos
      Sería la revancha de herramientas como Rational Unified Process y Enterprise Architect
      La diferencia es que, en vez de diagramas UML, llegarán archivos markdown
  • Esto parece útil para el lado de herramientas de infraestructura
    Por ejemplo, se puede imaginar un bundler escrito en Ruby pero compilado de forma estática, que además cumpla el papel de herramienta de instalación de Ruby como RVM
    El buildpack actual de Ruby está escrito en Ruby, pero obliga a hacer bootstrap con bash, lo cual es molesto y genera casos borde
    CNB se escribió en Rust para evitar ese problema, y la idea de poder distribuir un binario único sin dependencias es realmente poderosa