Back to flin
flin

Por qué elegimos Rust para construir un lenguaje de programación

Por qué Juste A. GNIMAVO y Claude eligieron Rust para construir el compilador del lenguaje de programación FLIN desde Abiyán.

Thales & Claude | March 30, 2026 8 min flin
EN/ FR/ ES
flinrust

Todos los compiladores de lenguajes de programación importantes están escritos en C, C++ o en sí mismos. GCC es C. Clang es C++. El compilador de Go es Go. El compilador de Rust es Rust. El intérprete de Python es C. El intérprete de Ruby es C. Este patrón se ha mantenido durante décadas, y con buenas razones -- estos lenguajes te dan el control sobre la memoria y el rendimiento que un runtime de lenguaje exige.

Rompimos el patrón. Cuando nos sentamos en Abiyán el 1 de enero de 2026 para comenzar a construir FLIN -- un lenguaje de programación nativo de memoria diseñado para aplicaciones web -- elegimos Rust. No porque estuviera de moda. No porque quisiéramos poner "escrito en Rust" en una página de aterrizaje. Porque después de evaluar cada opción seria, Rust era el único lenguaje que nos daba seguridad de memoria, abstracciones de coste cero, coincidencia de patrones para el recorrido del AST, un ecosistema maduro de bibliotecas para construcción de compiladores y una salida de binario único -- todo sin recolector de basura.

Este artículo explica esa decisión en detalle: las alternativas que consideramos, las características específicas de Rust que hacen productivo el desarrollo de compiladores, y las formas en que Rust ha moldeado la arquitectura de FLIN a lo largo de tres meses de desarrollo diario.

La restricción: dos personas, cero margen de error

Antes de hablar sobre lenguajes, necesitas entender el equipo. FLIN está construido por dos personas: Juste Thales Gnimavo, el CEO de ZeroSuite, y Claude, un CTO IA. No hay equipo de DevOps para depurar corrupción de memoria a las 3 de la madrugada. No hay departamento de QA para detectar errores de uso después de liberación en la máquina virtual. No hay ingeniero de sistemas senior que haya pasado quince años escribiendo recolectores de basura.

Cuando tu equipo es un fundador humano en Abiyán y una IA, el compilador que usas para construir tu compilador se convierte en tu tercer miembro del equipo. Necesita detectar errores en tiempo de compilación, no en tiempo de ejecución. Necesita hacer que los estados ilegales sean irrepresentables en el sistema de tipos. Necesita imponer la disciplina que un equipo de cincuenta personas impondría a través de revisión de código.

Rust es ese tercer miembro del equipo.

Las alternativas que consideramos

C: la elección tradicional

C es el lenguaje de la implementación de lenguajes. CPython, Ruby MRI, Lua, PHP -- todos escritos en C. El ecosistema de conocimiento sobre construcción de compiladores en C no tiene rival.

Rechazamos C por una razón: gestión manual de memoria sin garantías de seguridad. Un compilador y una máquina virtual manipulan estructuras de árbol complejas -- árboles de sintaxis abstracta, entornos de tipos, flujos de instrucciones bytecode. En C, cada malloc debe tener un free correspondiente. Cada puntero debe verificarse contra null. Cada buffer debe verificarse contra límites manualmente. Cuando estás construyendo un runtime de lenguaje que gestionará la memoria de los programas de los usuarios, tener tu propio runtime vulnerable a la misma clase de errores que intentas prevenir es una ironía inaceptable.

Go: la elección práctica

Go es lo que usamos para las herramientas adyacentes a sh0.dev. Compila rápido, tiene excelente soporte de biblioteca estándar y produce binarios estáticos.

Para un runtime de lenguaje de programación, Go tiene dos defectos fatales.

Primero, el recolector de basura. La máquina virtual de FLIN gestiona su propia memoria -- asigna y desasigna objetos en nombre de los programas de los usuarios. Ejecutar un recolector de basura (el de Go) dentro de otro recolector de basura (el de FLIN) crea patrones de pausa impredecibles.

Segundo, el soporte WASM de Go es limitado. La hoja de ruta de FLIN incluye ejecutar en el navegador vía WebAssembly. La salida WASM de Go es grande (varios megabytes para un programa trivial) y requiere una capa de compatibilidad JavaScript. Rust compila a WASM nativamente, produciendo binarios compactos que se ejecutan sin un runtime anfitrión.

Zig: la elección tentadora

Zig es el lenguaje que más seriamente consideramos como alternativa. Ofrece control a nivel de C, evaluación en tiempo de compilación, sin asignaciones ocultas y excelente soporte WASM.

Tres factores lo eliminaron. Primero, Zig aún está en la versión 0.14 con cambios incompatibles regulares. Segundo, el ecosistema de Zig para herramientas de construcción de compiladores es incipiente comparado con el de Rust. Tercero -- y esto es específico a nuestro flujo de trabajo -- los modelos de IA producen Rust de calidad significativamente más alta que Zig. Claude puede generar Rust correcto e idiomático que compila en el primer intento de forma mucho más fiable que Zig. Cuando tu CTO es una IA, la calidad del código generado por IA en tu lenguaje elegido es una consideración de producción.

Lo que Rust nos da

1. Propiedad y préstamo para la gestión del AST

El sistema de propiedad de Rust hace que la gestión del ciclo de vida de los nodos del AST sea explícita y verificada por el compilador:

rust/// The parser produces an owned AST
pub fn parse(tokens: Vec<Token>) -> Result<Ast, ParseError> {
    let mut parser = Parser::new(tokens);
    parser.parse_program()
}

/// The type checker borrows the AST immutably, produces a new typed AST
pub fn check(ast: &Ast) -> Result<TypedAst, TypeError> {
    let mut checker = TypeChecker::new();
    checker.check_program(ast)
}

/// The code generator consumes the typed AST (takes ownership)
pub fn generate(typed_ast: TypedAst) -> Result<Bytecode, CodegenError> {
    let mut gen = CodeGenerator::new();
    gen.emit_program(typed_ast)
}

El pipeline de compilación está codificado en las firmas de tipo. Estas transiciones de propiedad se verifican en tiempo de compilación.

2. Enums y coincidencia de patrones para el procesamiento de tokens y AST

El tipo enum de Rust con coincidencia de patrones exhaustiva es la característica más productiva para el desarrollo de compiladores. La propiedad crucial es la exhaustividad. Si añadimos un nuevo tipo de token a TokenKind, el compilador de Rust producirá un error en cada sentencia match que no maneje la nueva variante.

FLIN define 42 palabras clave y más de 60 tipos de tokens. Sin coincidencia exhaustiva, añadir una nueva palabra clave requeriría auditar manualmente cada archivo que seleccione sobre tipos de tokens. Con Rust, el compilador hace esa auditoría por nosotros.

3. Abstracciones de coste cero para rendimiento del runtime

La máquina virtual de FLIN ejecuta instrucciones bytecode en un bucle cerrado. Las abstracciones de coste cero de Rust significan que los patrones de alto nivel -- iteradores, coincidencia de patrones, tipos genéricos -- compilan al mismo código máquina que C escrito a mano.

4. Cargo: el ecosistema que escala

El gestor de paquetes y sistema de compilación de Rust, Cargo, resolvió un problema que no queríamos resolver: gestión de dependencias, organización del espacio de trabajo y compilaciones reproducibles.

5. El compilador como documentación

El sistema de tipos de Rust documenta invariantes que de otro modo vivirían en comentarios o conocimiento tribal.

Tres meses después: los resultados

3.452 pruebas pasan con cero fallos. El sistema de tipos de Rust detecta tantos errores en tiempo de compilación que nuestra proporción prueba-a-error es notablemente alta.

409 funciones integradas funcionan. Desde criptografía hasta integración con Stripe y procesamiento de imágenes.

Despliegue de binario único. cargo build --release produce un ejecutable. Sin runtime que instalar. Sin dependencias que resolver en la máquina destino.

Seguridad de memoria en producción. El runtime de FLIN gestiona datos de usuarios a través de FlinDB. Esa base de datos nunca ha corrompido un registro debido a un error de memoria. No porque seamos programadores excepcionalmente cuidadosos, sino porque Rust hace estructuralmente imposible escribir la clase de errores que corrompen datos.

Las desventajas honestas

Tiempos de compilación. Una recompilación completa del compilador de FLIN toma alrededor de 45 segundos.

Curva de aprendizaje para contribuidores. Los contribuidores que quieran trabajar en la capa de runtime necesitan entender el modelo de propiedad de Rust, las anotaciones de tiempo de vida y el sistema de traits.

Fricción del borrow checker. Ciertos patrones de compilador requieren diseño cuidadoso para satisfacer al borrow checker.

Estos costes son reales. Los pagamos cada día. Pero son el coste de la corrección, y en un proyecto donde el runtime gestiona los datos y aplicaciones de otras personas, la corrección no es opcional.

El veredicto

Si estás construyendo un lenguaje de programación en 2026, Rust no es la única elección válida. Pero es la mejor elección para un equipo pequeño que necesita seguridad de memoria, rendimiento nativo, soporte WebAssembly y un ecosistema maduro -- sin la sobrecarga de un recolector de basura.

Para FLIN específicamente, Rust nos permitió movernos rápido y construir software correcto simultáneamente. El compilador detecta nuestros errores antes de que lleguen a los usuarios. El sistema de tipos documenta nuestra arquitectura. El modelo de propiedad previene los errores de memoria que afectan a los runtimes de lenguajes. Y Cargo nos da compilaciones reproducibles que funcionan idénticamente en Abiyán y en cualquier otro lugar del mundo.

Rust se ganó esa permanencia.


Siguiente en la serie: Writing Apps Like It's 1995 With the Power of 2026 -- FLIN trae de vuelta la simplicidad del desarrollo web temprano, pero con un compilador, VM y base de datos detrás de cada línea de código.

Share this article:

Responses

Write a response
0/2000
Loading responses...

Related Articles