Archivo de la etiqueta: groovy

Transformaciones AST para importar clases de IDL

En la anterior entraba hablaba un poco sobre las transformaciones AST de Groovy y que me maravillaban (y si esto último no lo dije, lo digo ahora). Como me gustan y las veo útiles decidí ponerlas en práctica para un uso real.

En donde trabajo se utiliza un lenguaje de programación llamado IDL. Este lenguaje se utilizan en muchos entornos de investigación y para ser sinceros se haría un favor al mundo amputándole las manos a la persona o personas que lo diseñó/aron (pero dejemos esto para un posible futuro artículo). En IDL se pueden crear funciones y procedimientos o se puede crear clases con métodos y atributos. Cuando se necesita ofrecer a otro lenguaje de las funcionalidades que hemos creado en IDL se hace uso siempre de clases y objetos. Además provee de una herramientas denominada Export Bridge Assistant (EBA) para facilitar la tarea de generar los bindings del lenguaje destino. Debo decir que me EBA hace cierto trabajo por el programador, concretamente genera una clase en java o .Net con los métodos seleccionados, pero en el caso de Java no hace distinción de los tipos de datos. Para él solo existe el JIDLNumber, pero está prohibido por el programador su uso, sino que debes utilizar JIDLFloat, JIDLLong, etc. Además, estos tipos de datos no son nativos de Java lo que supone un sobreesfuerzo para el programador.

En esta situación se me ocurrió crear una transformación AST que generase el código de los métodos usando datos nativos de Java. En lugar de llamar a EBA para generar el binding se crea una clase de esta forma:

1
2
3
4
5
@IDLClass(idlclass="CLASE_DE_IDL")
class MiClaseEnJava extends JIDLObject {
   @IDLFunction(name="FUNCION_IDL")
   float miFuncion(float a, float b, String cadena) {}
}

Durante la compilación de la clase se detecta la nota IDLClass y se pasa el control a la transformación AST que añade un constructor por defecto necesario para los objetos que heredan de JIDLObject. Además se busca de nota IDLFunction y cuando se encuentra se interpretan los parámetros para generar el código con las transformaciones de tipos necesarias.

Sinceramente creo que esto es más óptimo que hacer uso de EBA, ya que de todos modos me termino creando métodos que realizan la transformación de tipos y de este modo me ahorro dicho trabajo.

Lo que más me ha costado es entender como funciona la generación de código ya que se basa en la estructura del compilador. Concretamente me ha constado 1 semana hacer la transformación.

En cuanto pueda publicaré el código para que lo pueda utilizar quien quiera, que seguro que mal no hará.

Haciendo memoria

Esta semana he recordado uno de mis viejos proyectos de cuando era más joven (sería el año 97). En aquel momento tenía en mente la creación de un lenguaje que pudiese ser modificado en tiempo de compilación. Con esto me refiero a que pudiesen crearse reglas que permitieran modificar el cómo este compilaba o añadiese nuevas posibilidades al lenguaje.

En aquel momento yo no tenía conocimiento alguno de lenguajes, gramáticas o compiladores y el único curso que vi fue el de la revista Solo Programadores de varios años atrás y, la verdad, no me resolvió ninguna duda (esto se debe a que entonces no solía leer tanto y miraba solo por encima las cosas).

El caso es que me he encontrado que ya lo han inventado. En Groovy existe una característica denominada transformaciones AST que permite modificar las reglas de compilación.  Debo reconocer que es una característica tan chula como difícil de utilizar (todo hay que decirlo).

En estos momentos me encuentro estudiando la documentación para ponerme a hacer pruebas y comprobar qué tal funciona. La verdad es que permite hacer cosas tan increíbles como Groovy++, que es un optimizador de Groovy (lo que hace es eliminar algunas características de Groovy para acelerar la ejecución de las aplicaciones).

He podido encontrar una gran cantidad de ejemplo y la verdad es que me sorprenden mucho. Por ejemplo se pueden automatizar patrones de diseño con este sistema tal y como se hace con la transformación Bindable. Ésta convierte un atributo de clase en un sistema que permite monitorizar los cambios del mismo (patron ). De este modo si tenemos algo como:

1
2
3
class ClaseDeEjemplo {
    @Bindable String prop
}

Se transformará de forma automática en:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class ClaseDeEjemplo {
    private String prop
    PropertyChangeSupport pcs = new PropertyChangeSupport(this);
    public void addPropertyChangeListener(PropertyChangeListener l) {
        pcs.add(l);
    }
 
    public void removePropertyChangeListener(PropertyChangeListener l) {
        pcs.remove(l);
    }
 
    public String getProp() {
        return prop;
    }
 
    public void setProp(String prop) {
        pcs.firePropertyChanged("prop", this.prop, this.prop = prop);
    }
}

Con lo que evitamos tener que escribir un gran número de líneas de código. Sinceramente me parece un gran avance.

Aprendiendo Grails

La verdad es que últimamente me encuentro algo perro y escribo poco en la bitácora, lo cual no me molestaría lo más mínimo si no fuera porque casi cada día se me ocurre algo que escribir en ella.

Una de estas cosas que me están ocurriendo actualmente es que estoy aprendiendo a programar en Groovy para utilizarlo junto a Grails. ¿Y qué serán estos “insultos” que acabo de soltar? Pues Grails es un conjunto de herramientas que busca ayudar a hacer aplicaciones web de forma rápida gracias al uso de convenciones. Para los que sepan un poco de qué va todo esto, es una copia de Ruby on Rails (RoR, de aquí en adelante), pero utilizando herramientas Java.

El caso es que no lo he elegido frente a RoR por ser mejor que este ni más bonito. Lo he elegido porque tiene buena compatibilidad con Java y así puedo aprovechar cosas que ya tenía desarrolladas en este otro lenguaje (ahorrándome tiempo de desarrollo).

Ahora estoy haciendo una aplicación para la beca. No será muy compleja y me servirá para comprobar como funciona esta arquitectura. De momento las pruebas son realmente prometedoras :)