Motor de ejecución del lenguaje Umbral. Interpreta y ejecuta el AST generado por el parser.
Ejecuta el código Umbral evaluando el AST, manejando variables, funciones, clases y control de flujo.
use umbral_lexer::analizar;
use umbral_parser::Parser;
use umbral_runtime::Runtime;
let codigo = "v: x = 10; tprint(x);";
let tokens = analizar(codigo);
let mut parser = Parser::nuevo(tokens);
let programa = parser.parsear_programa().unwrap();
let mut runtime = Runtime::nuevo();
runtime.ejecutar(programa);Runtime
└── Interpretador
├── Entorno (variables y constantes)
├── GestorClases (definiciones de clases)
├── GestorFunciones (ejecución de funciones)
└── Sistema de valores
Define todos los tipos de valores en Umbral:
pub enum Valor {
Entero(i64),
Flotante(f64),
Texto(String),
Booleano(bool),
Lista(Vec<Valor>),
Diccionario(HashMap<String, Valor>),
Objeto(Instancia),
Funcion(Funcion),
Nulo,
}Gestiona el scope de variables y constantes:
pub struct Entorno {
variables: HashMap<String, Valor>,
constantes: HashSet<String>,
padre: Option<Box<Entorno>>,
}Características:
- Scope anidado con cadena de padres
- Protección de constantes
- Búsqueda en cascada
Maneja definiciones de clases e instancias:
pub struct Clase {
pub nombre: String,
pub propiedades: HashMap<String, Valor>,
pub metodos: HashMap<String, Metodo>,
pub constructor: Option<Metodo>,
}Ejecuta funciones con binding de parámetros:
pub struct GestorFunciones;
impl GestorFunciones {
pub fn ejecutar_funcion(
func: &Funcion,
argumentos: Vec<Valor>,
interprete: &mut Interpretador,
) -> Valor;
}Núcleo de ejecución del runtime:
Métodos principales:
ejecutar_sentencia()- Dispatcher de sentenciasevaluar_expresion()- Evaluador de expresionesejecutar_bloque()- Ejecución de bloques con scope
Operaciones:
- Aritméticas:
+,-,*,/,% - Comparación:
==,!=,<,>,<=,>= - Lógicas:
&&,||,! - Incremento/Decremento:
++,--
Control de flujo:
ejecutar_if()- If/else if/elseejecutar_switch()- Switch/case/defaultejecutar_for()- Bucle forejecutar_foreach()- Bucle foreachejecutar_while()- Bucle whileejecutar_do_while()- Bucle do-whileejecutar_try_catch()- Manejo de excepcionesejecutar_throw()- Lanzamiento de errores
Funcionalidades especiales:
- Interpolación de strings con
&variable - Acceso a propiedades con
. - Acceso a índices con
[] - Instanciación de clases
- Llamadas a métodos
use umbral_lexer::analizar;
use umbral_parser::Parser;
use umbral_runtime::Runtime;
fn main() {
let codigo = r#"
v: contador = 0;
wh: (contador < 5) {
tprint(contador);
contador++;
}
f: factorial(n->Int)->Int {
i: (n <= 1) {
r: (1);
} e: {
r: (n * factorial(n - 1));
}
}
tprint(factorial(5));
"#;
let tokens = analizar(codigo);
let mut parser = Parser::nuevo(tokens);
let programa = parser.parsear_programa().unwrap();
let mut runtime = Runtime::nuevo();
runtime.ejecutar(programa);
}- ✅ Declaración con tipos opcionales
- ✅ Asignación y reasignación
- ✅ Protección de constantes
- ✅ Scope léxico
- ✅ Declaración con parámetros tipados
- ✅ Retorno de valores
- ✅ Recursión
- ✅ Closure sobre scope
- ✅ Declaración con propiedades
- ✅ Constructor
- ✅ Métodos
- ✅ Instanciación con
n: - ✅ Acceso a propiedades con
.
- ✅ Aritméticos con promoción de tipos
- ✅ Comparación con coerción
- ✅ Lógicos con evaluación cortocircuito
- ✅ Incremento/Decremento
- ✅ If/else if/else
- ✅ Switch/case/default
- ✅ For con inicialización
- ✅ ForEach sobre iterables
- ✅ While
- ✅ Do-While
- ✅ Try-Catch-Finally
- ✅ Throw
- ✅ Captura de excepciones
- ✅ Propagación de errores
- ✅ Clase Error nativa
- ✅ Arrays con acceso por índice
- ✅ Objetos/Diccionarios
- ✅ Propiedad
.lengthen arrays - ✅ Operador spread (
&) para expandir arrays
- ✅ Strings simples (
'texto') - ✅ Strings con interpolación (
"Hola &nombre") - ✅ Strings multilínea (
'''texto''')
- ✅
tprint()- Impresión en consola
El runtime está implementado siguiendo principios de código limpio:
- ❌ Sin if-else anidados
- ✅ Uso de early returns
- ✅ Funciones pequeñas con responsabilidad única
- ✅ Nombres descriptivos
- ✅ Extracción de métodos
- ✅ Uso de operadores funcionales (map, and_then)
- Interpretación directa del AST
- Gestión eficiente de scope con HashMap
- Clonación mínima de valores