REPL – Interfaz de Línea de Comandos Interactiva
Archivo: src/repl.rs — 315 líneas
¿Por qué existe?
El REPL (Read-Eval-Print Loop) permite a los usuarios escribir y ejecutar fragmentos de código
Forja en tiempo real, facilitando pruebas rápidas, depuración y exploración del lenguaje sin
necesidad de crear archivos fuente. Es la herramienta ideal para aprendizaje, experimentación
y scripting rápido.
Estructura principal
REPL
| Campo | Tipo | Descripción |
vm_mode | String | Modo de VM a utilizar: "fast" (ForjaFast con NaN tagging, default) o "jit" |
buffer | String | Buffer de entrada acumulada para expresiones multi-línea |
show_bytecode | bool | Si es cierto, muestra el bytecode generado antes de ejecutar |
source_acumulado | String | Código fuente completo acumulado desde el inicio de la sesión |
rl | Editor<()> | Editor de línea de rustyline con historial y edición |
vm_fast | Option<ForjaFast> | Instancia de la VM rápida (modo fast), contenida en Option |
Métodos públicos
REPL::new()
| Firma | Descripción |
pub fn new(modo: &str) -> Self |
Crea una nueva instancia del REPL. Inicializa rustyline con historial, configura el
modo de VM según el string recibido ("fast", "jit", etc.),
y prepara los buffers de código fuente.
|
REPL::iniciar()
| Firma | Descripción |
pub fn iniciar(&mut self) | Método principal (~180 líneas). Bucle principal de lectura-ejecución:
- Muestra el prompt
>>> y lee una línea con rustyline - Agrega la línea al buffer de entrada acumulada
- Verifica si la entrada está completa (
chequear_completud()) - Si está completa, pasa por el pipeline completo:
- Lexer: tokeniza
source_acumulado + buffer - Parser: construye el AST (
Programa) - Generación de bytecode: compila a opcodes
- Ejecución: corre en la VM seleccionada (ForjaFast o clásica)
- Muestra el resultado
- Si está incompleta, espera más líneas
- Maneja comandos especiales (ver abajo)
|
Comandos del REPL
| Comando | Descripción |
:salir / :quit | Sale del REPL |
:reset / :limpiar | Reinicia el estado de la VM (limpia variables, funciones, heap) |
:reload | Recarga todos los módulos (re-parsea y re-compila desde las fuentes originales) |
:reload modulo | Recarga un módulo específico por su nombre |
:variables | Muestra las variables definidas actualmente (solo modo fast) |
:bytecode | Alterna la visualización del bytecode generado |
Métodos privados
REPL::compilar_y_ejecutar()
| Firma | Descripción |
fn compilar_y_ejecutar(&mut self, source: &str) -> Result<String, String> |
Pipeline completo de compilación + ejecución (~44 líneas):
- Tokeniza el código fuente acumulado + la nueva línea
- Parsea los tokens a AST
- Genera bytecode a partir del AST
- Si show_bytecode está activo, muestra los opcodes generados
- Si el modo es
"fast" (o cualquier otro): carga el bytecode en ForjaFast y ejecuta con ejecutar() - Retorna el resultado formateado como String
En caso de error (léxico, sintáctico, semántico o de runtime), retorna el mensaje de error.
|
REPL::chequear_completud()
| Firma | Descripción |
fn chequear_completud(&self) -> bool |
Verifica si el buffer acumulado está completo contando llaves { y }.
Si están balanceadas (misma cantidad), la entrada está completa y se ejecuta.
Si hay más llaves abiertas que cerradas, espera más líneas de entrada.
|
Pipeline del REPL
┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────────┐ ┌─────────────┐
│ Entrada │──▶│ Lexer │──▶│ Parser │──▶│ Bytecode Gen │──▶│ VM (fast/ │
│ usuario │ │ tokens │ │ AST │ │ opcodes │ │ jit) │
└──────────┘ └──────────┘ └──────────┘ └──────────────┘ └──────┬──────┘
│
▼
┌──────────────┐
│ Resultado / │
│ Error │
└──────────────┘
Hot-reload de módulos
El REPL soporta recarga en caliente de módulos mediante :reload. Cuando se recarga
un módulo, el sistema:
- Resuelve el módulo por su nombre a través del
ModuleResolver - Obtiene el bytecode actualizado con
generar_para_modulo() - Llama a
hot_swap_module() en ForjaFast para reemplazar el bytecode en caliente - Las funciones actualizadas se reemplazan sin detener la ejecución
Relación con el resto del compilador
- Depende de
lexer.rs, parser.rs, bytecode.rs para el pipeline de compilación - Ejecuta el código en
vm_fast.rs (ForjaFast) - Utiliza
module.rs (ModuleResolver) para recarga de módulos - Se invoca desde la CLI (
main.rs) con el flag --repl