A medida que avanzaba con el diseño de MateScript apareció una pregunta interesante.
¿Cómo agregamos azúcar sintáctico al lenguaje sin llenar el compilador de casos especiales?
Muchos lenguajes modernos terminan incorporando nuevas palabras reservadas, operadores o construcciones que solo existen porque el compilador las reconoce de forma explícita.
Quería explorar un enfoque diferente.
¿Y si gran parte del azúcar sintáctico pudiera implementarse fuera del compilador?
Así nacieron los Transforms.
¿Qué es un Transform?
Un Transform es una regla declarativa que toma una construcción sintáctica y la reemplaza por otra antes de que el compilador comience el análisis semántico.
La idea es extremadamente simple.
Cuando encuentres esto...
↓
Reemplázalo por esto.
No ejecuta código.
No modifica el compilador.
No realiza reemplazos de texto.
Simplemente transforma una representación sintáctica en otra.
En artículos anteriores decidimos que el desarrollador podrá escribir:
let name: String?;
Internamente eso es equivalente a:
let name: Optional<String>;
En lugar de implementar esta característica directamente dentro del compilador, podemos definir un Transform.
transform Nullable {
T?
=>
Optional<T>
}
A partir de ese momento, cualquier aparición de:
String?
será transformada automáticamente en:
Optional<String>
El compilador nunca necesita conocer el operador ?.
Supongamos que MateScript decide no incorporar arrays como estructura del lenguaje.
Sin embargo, muchos desarrolladores están acostumbrados a escribir:
Int[10]
Podemos definir otro Transform.
transform Arrays {
T[N]
=>
ArrayList<T>(N)
}
El resultado será equivalente a:
ArrayList<Int>(10)
Nuevamente, el compilador no necesita incorporar una característica nueva.
Simplemente aplica una transformación.
Una decisión importante es mantener estas reglas separadas del código fuente.
Los archivos de MateScript utilizarán la extensión: .mt
Mientras que los Transforms vivirán en archivos independientes: .tmt
Por ejemplo:
src/
main/
matescript/
Person.mt
Main.mt
transforms/
nullable.tmt
arrays.tmt
collections.tmt
De esta manera, el código de la aplicación permanece limpio y las transformaciones pueden evolucionar de forma independiente.
No todos los Transforms tendrán que ser escritos por el desarrollador.
El propio SDK de MateScript incluirá un conjunto de transformaciones oficiales.
Por ejemplo:
- Nullable (T? -> Optional<T>)
- Colecciones
- Rangos
- Literales
- Otras construcciones de alto nivel
El desarrollador simplemente las utilizará sin preocuparse por su implementación.
Lo realmente interesante aparece cuando cualquier biblioteca puede distribuir sus propios Transforms.
Imaginemos una librería para programación reactiva.
Podría incluir nuevas construcciones sintácticas sin modificar el compilador.
Lo mismo podría ocurrir con librerías para SQL, testing, concurrencia o cualquier otro dominio.
En lugar de esperar una nueva versión del lenguaje, la comunidad podría extenderlo mediante nuevos Transforms.
¿Son macros? No exactamente.
Cuando escuchamos la palabra macro, solemos pensar en sistemas capaces de ejecutar código durante la compilación o incluso modificar el propio compilador.
Ese no es el objetivo de MateScript.
Los transforms son mucho más simples.
Son reglas declarativas de transformación sintáctica.
No realizan reemplazos de texto.
No tienen acceso al sistema de archivos.
No ejecutan código arbitrario.
No cambian el comportamiento del compilador.
Su única responsabilidad es transformar una construcción sintáctica en otra equivalente.
Gracias a este mecanismo, el compilador incorpora una nueva etapa.
Código fuente (.mt)
│
▼
Lexer
│
▼
Parser
│
▼
AST de sintaxis
│
▼
Carga de Transforms
(SDK + proyecto)
│
▼
Motor de Transforms
│
▼
AST transformado
│
▼
Análisis semántico
│
▼
Generación de bytecode
El analizador semántico siempre trabaja sobre un único modelo del lenguaje.
No necesita conocer las distintas formas sintácticas que utilizaron los desarrolladores.
Quizás el aspecto más interesante de esta idea sea filosófico.
En lugar de incorporar cientos de características al compilador, MateScript puede mantener un núcleo pequeño y estable.
Las construcciones de alto nivel pueden implementarse mediante Transforms reutilizables.
Esto hace que el lenguaje sea más fácil de mantener, más sencillo de aprender y mucho más flexible para evolucionar con el tiempo.
Los Transforms representan una de las ideas más ambiciosas de MateScript.
Permiten agregar azúcar sintáctico sin modificar el compilador, mantienen el lenguaje pequeño y ofrecen una forma sencilla para que tanto la SDK como la comunidad puedan extender el lenguaje.
En cierto modo, los Transforms convierten al compilador en una plataforma sobre la cual pueden construirse nuevas formas de escribir código, sin perder coherencia ni simplicidad.








