Monomorfización de Genéricos
Archivo: src/monomorph.rs (605 líneas)
¿Por qué existe?
Detecta todas las instanciaciones concretas de genéricos en un programa y genera versiones especializadas para cada tipo concreto. Esto elimina el dispatch dinámico (sin boxing ni vtables en las llamadas) y habilita optimizaciones como inlining y dead code elimination sobre cada versión tipada. Es la técnica clásica de C++/Rust aplicada al compilador de Forja.
Ejemplo
clase Caja<T> { valor: T }
funcion obtener<T>(c: Caja<T>) -> T { retornar c.valor }
variable c1 = nueva Caja<Entero> { valor: 42 }
variable c2 = nueva Caja<Texto> { valor: "hola" } Se genera:
Caja_Entero { valor: Entero }— clase especializadaobtener_Entero(c: Caja_Entero) -> Entero— función especializada
Estructuras clave
| Componente | Descripción |
|---|---|
ConcreteType | Representa un tipo concreto monomorfizable: Entero, Decimal, Texto, Booleano, Nulo, Exacto, Clase(String), Arreglo, Resultado, Opcion |
GenericInstantiation | Instanciación detectada: nombre original, type_args (parámetro → tipo concreto) y specialized_name resultante |
Monomorphizer | Recolector y generador: registros de funciones/clases genéricas, instanciaciones y declaraciones especializadas |
FuncionGenerica / ClaseGenerica | Definiciones genéricas extraídas (parámetros de tipo, parámetros, cuerpo / campos y métodos) |
Pipeline (3 fases)
| Fase | Método | Descripción |
|---|---|---|
| 1 — Extracción | extract_generics | Recorre las declaraciones y guarda funciones (parametros_tipo no vacío) y clases genéricas |
| 2 — Recolección | collect_instantiations | Recorre variables, cuerpos de funciones y métodos; detecta llamadas a funciones genéricas e instanciaciones de clases |
| 3 — Especialización | specialize | Genera una Declaracion por instanciación con parámetros de tipo reemplazados por tipos concretos |
Inferencia de tipos
Para funciones, infer_type_args_for_fn recorre cada parámetro de tipo, encuentra el primer parámetro de la función que lo usa (tipo_usa_parametro) y extrae el tipo concreto del argumento correspondiente en la llamada. Para clases, infer_type_args_for_class infiere del primer argumento (si hay un solo parámetro de tipo) o mapea por posición. infer_concrete_from_expr resuelve directamente literales (número, decimal, texto, booleano, nulo, exacto, arreglos por su primer elemento); las variables requieren el type checker y retornan None.
Generación de nombres especializados
ConcreteType::name() produce identificadores legibles: Arr_Entero para arreglos, Result_A_B para resultados, Opt_T para opciones. El nombre especializado de una instanciación se forma como nombre_tipo1_tipo2 (ej. obtener_Entero), y se evitan duplicados comparando specialized_name.
Cómo se integra
El monomorphizer corre como una pasada sobre el AST (ast::Programa) antes de la compilación a bytecode: reemplaza los tipos Parametro por los concretos en parámetros, retorno y campos con replace_type_params, y devuelve las declaraciones especializadas con get_specializations para que el resto del pipeline las compile como funciones/clases normales.
ConcreteType::from_tipo no monomorfiza tipos función ni RasgoObjeto, y los Parametro sin resolver retornan None: la monomorfización solo actúa sobre tipos concretos.