Una implementación moderna de Wollok en Rust, enfocada en la enseñanza de programación orientada a objetos.
- 🎯 Objetivo
- 🔥 Progreso reciente
- ✨ Características
- 🚀 Instalación
- 📚 Documentación del Lenguaje
- 🏗️ Arquitectura
- 🤝 Contribuir
- 📜 Licencia
Wollok-rs es una reimplementación de Wollok en Rust que busca:
- Mejor rendimiento: Aprovechando la velocidad y seguridad de Rust
- Modularidad: Arquitectura basada en crates independientes
- Extensibilidad: Diseño que facilita nuevas características
- Compatibilidad: Mantener la esencia pedagógica de Wollok original
Esto dejó de ser "solo parser": hay un compilador (wollok-compiler) que baja el AST a bytecode y una VM (wollok-vm) que lo corre de punta a punta. cargo run -- archivo.wlk ejecuta Wollok de verdad, no solo lo tokeniza.
- Dispatch por inline cache polimórfica (4 slots) para los sends a objetos, con el mismo criterio que usan los intérpretes adaptativos de verdad.
- Los primitivos (
Int/Float/Bool/Str) nunca son objetos de heap: despachan contra una tabla nativa en Rust (wollok_vm::native), sin el costo de boxear cada entero. - La stdlib (
wollok-std) es una crate aparte, no está hardcodeada en la VM — cada método nativo es una función suelta, registrada por selector, para que crecer la librería no implique tocar el intérprete. consolees Wollok real, compilado como cualquierobject, conprintlndeclaradonativey aridad variable.property/const propertygeneran getter y setter solos, como en el Wollok original.
Ejemplos que corren de verdad (no pseudocódigo) en examples/. Lo que falta (arrays/sets, closures, inherits/super, try/catch) está en docs/backlog.md; el porqué de cada decisión de diseño de la VM, en docs/vm-design.md.
Empezamos a medir wollok-rs contra wollok run (wollok-ts) sobre un corpus chico y aislado en bench/ — mismos dos programas, escritos una vez en cada dialecto. Con hyperfine (proceso completo, arranque incluido):
| Programa | wollok-rs | wollok-ts |
|---|---|---|
aritmetica (30 sends) |
~14 ms | ~1.2 s |
mensajes (30 sends cruzados) |
~14 ms | ~1.2 s |
Y por dentro, con criterion (benches/pipeline.rs, sin el print de la comparación anterior para no medir I/O):
| Fase | aritmetica |
mensajes |
|---|---|---|
| parseo | ~0.68 ms | ~0.85 ms |
| + compilación | ~0.72 ms | ~0.97 ms |
| + ejecución | ~0.72 ms | ~0.98 ms |
Por qué esto no es una comparación justa todavía: wollok-ts arranca una VM de Node completa por cada corrida (~1.2 s son mayormente eso, no "correr el programa"); wollok-rs es un binario nativo que arranca casi gratis. Y sobre todo — wollok-rs tiene casi nada de stdlib real (unos pocos métodos de Int/Bool/Str, sin Float, sin colecciones, sin closures, sin herencia) contra una implementación completa y madura. Comparar tiempos hoy es más "cuánto tarda arrancar cada runtime" que "qué tan rápido corre Wollok" — va a volverse una comparación real a medida que la stdlib y el lenguaje se acerquen en cobertura.
De paso, armar este benchmark encontró un bug real: wollok-lexer capturaba un stack backtrace completo (Backtrace::force_capture()) en cada intento de match fallido durante el backtracking normal del parser — hasta ~23 veces por token. Cambiarlo a Backtrace::capture() (que respeta RUST_BACKTRACE, casi gratis si no está seteado) hizo el lexer ~36x más rápido. Sin este tipo de benchmarks, ese bug seguía ahí.
- Literales: Números, strings, booleanos, null
- Colecciones: Arrays
[1, 2, 3]y Sets#{1, 2, 3} - Objetos: Declaración con
objecty cuerpo con propiedades/métodos - Variables:
const(inmutables) ylet(mutables) - Propiedades: Con
propertypara getters/setters automáticos - Métodos: Con parámetros y cuerpos de bloque o inline
- Comentarios: Soporte para
//comentarios de línea - Asignaciones: Expresiones de asignación con
=
- Clases: Declaración, constructores, herencia
- Manejo de Errores:
falliblemethods con?(propagación) y!(assertion) - Closures: Sintaxis simple
() => expr(sin llaves) - Imports: Sistema de módulos e importaciones
- Tests: Framework de testing integrado
- Wollok Game: Librería para juegos
- Mixins: Composición de comportamiento
- Herencia:
inheritskeyword ysupercalls - Polimorfismo: Dynamic dispatch
- REPL: Consola interactiva
- LSP: Language Server Protocol
- Debugging: Soporte para debuggers
- Rust 1.80+ (Instalar Rust)
git clone https://github.com/romancitodev/wollok-rs.git
cd wollok-rs
cargo build --release# Ejecutar el ejemplo incluido
cargo run
# Con logs de debug
RUST_LOG=debug cargo runLa documentación completa del lenguaje está organizada en módulos:
- Características Básicas: Variables, literales, comentarios
- Objetos: Declaración, propiedades, métodos
- Colecciones: Arrays, sets, operaciones
- Expresiones: Asignaciones, llamadas a métodos
- Características Avanzadas: Features planeadas para el futuro
- Comparación con Wollok Original: Diferencias y similitudes
object calculadora {
property memoria = 0
method sumar(a, b) = a + b
method guardarEnMemoria(valor) {
memoria = valor
}
method recuperarMemoria() = memoria
}
const resultado = calculadora.sumar(5, 3)
calculadora.guardarEnMemoria(resultado)El proyecto está organizado en varios crates:
wollok-rs/
├── crates/
│ ├── wollok-lexer/ # Tokenización y análisis léxico
│ ├── wollok-ast/ # Parser y AST
│ ├── wollok-common/ # Tipos y utilidades compartidas
│ ├── wollok-compiler/ # AST -> bytecode
│ ├── wollok-vm/ # La VM: heap, dispatch, el intérprete
│ ├── wollok-std/ # Stdlib nativa (Int/Float/Bool/Str, console)
│ └── wollok-cli/ # Interfaz de línea de comandos
└── src/ # Ejecutable principal
- Lexer (
wollok-lexer): Convierte texto a tokens - Parser (
wollok-ast): Genera AST desde tokens - Compilación (
wollok-compiler): AST a bytecode - Ejecución (
wollok-vm+wollok-std): la VM corre el bytecode, despachando a la stdlib nativa cuando hace falta
¡Las contribuciones son bienvenidas! Por favor:
- Fork el proyecto
- Crea tu feature branch (
git checkout -b feature/AmazingFeature) - Commit tus cambios (
git commit -m 'Add some AmazingFeature') - Push al branch (
git push origin feature/AmazingFeature) - Abre un Pull Request
# Ejecutar tests
cargo test
# Formatear código
cargo fmt
# Linter
cargo clippy
# Con just (opcional)
just test
just fmt
just clippyEste proyecto está licenciado bajo LICENSE - ver el archivo para detalles.
Nota: Este proyecto está en desarrollo activo. Muchas características están planeadas pero no implementadas. Ver issues para el estado actual.