jueves, julio 27, 2006

ST2JS - Traductor de Smalltalk a JavaScript (Parte I)

Hace tiempo que no publico nada en el blog, pero eso no fue debido a que estuve de vacaciones. Lo que ocurre es que sigo muy ocupado investigando sobre las posibilidades que brindan los navegadores de Internet actuales.

Live-Wiki

Para publicar los resultados de la investigación estoy haciendo un Live-Wiki. El Live-Wiki será Wiki sin modo edición, donde se se modificará el documento directamente (ver EditInPlace). Los cambios hechos en las páginas del wiki, serán enviadas al instante (usando Comet) a todos los usuarios conectados al wiki (y viendo esa página). También habrá un chat para los usuarios conectados a la página. Iré contando más del Live-Wiki conforme vaya avanzando en el desarrollo.

JavaScript

Para sacar beneficio de las prestaciones que ofrecen los navegadores de internet actuales es necesario escribir una buena cantidad de código JavaScript. El JavaScript es un lindo lenguajecito con algunos conceptos de objetos y funcionales que lenguajes supuestamente serios ni sueñan en tratar de proveer. Por otro lado, es un lenguaje basado en prototipos (no en clases) que permite jugar con diferentes políticas de herencia. Las funciones son, como corresponde, objetos y esto permite encapsular comportamiento de una forma similar a los bloques de Smalltalk. Para mejorar el panorama, las funciones en JavaScript son verdaderos block-closures.


ST2JS - Traductor de Smalltalk a JavaScript

Las características de JavaScript mencionadas anteriormente, usadas con picardía, permiten hacer un traductor de Smalltalk a JavaScript que respete toda la semántica del Smalltalk.

La semántica de las metaclases de Smalltalk podría lograrse utilizando un modelo similar al explicado en el paper "self includes: Smalltalk" (de Mario Wolczko).

Los bloques de Smalltalk se traducen más o menos directamente a funciones de JS. Sólo hay que considerar 2 diferencias: el this/self y la diferencia entre el return/^.

En Smalltalk, la pseudovariable self apunta al receptor del método donde se evalúa el bloque. En cambio, en JS, la pseudovariable this apunta al objeto función. Como las funciones de JS son verdaderos block-closures, este problema se resuelve fácilmente de la siguiente forma:

En Smalltalk:

SampleClass>>foo
    self collection do:[:each |
        each = 2
            ifTrue:[self bar: 1].
    ].

En JavaScript:

SampleClass.prototype.foo = function() {
    /* En este punto, this y self son lo mismo: El receptor del mensaje que activó el método */
    var self = this;
    self.collection().do_(function(each) {
     if (each = 2) {
         self.bar_(1); /* En este punto, this apunta a la función y no al receptor. Por eso usamos la variable self apoyándonos en los true-block-closures de JS */
     }
    });
}


La otra diferencia requiere un poco más de "magia" para resolverlo. El punto es que en Smalltalk, el ^ usado dentro de un bloque, hace terminar no sólo la evaluación del bloque, sino también del método donde se activó el bloque. En cambio, en JS, el return sólo sale de la función (es decir de 1 sólo nivel).

En Smalltalk:

SampleClass>>bar
    self collection do:[:each |
        each = 2
            ifTrue:[^ self bar].
    ].

En JavaScript:

SampleClass.prototype.bar = function() {
    var self = this;
    try {
        self.collection().do_(function(each) {
         if (each = 2) {
             throw new ReturnValue(self.bar_()); /* La excepción viajará hasta el catch(), es decir hasta el método */
         }
        });
    }
    catch (err) {
        if (err.constructor == ReturnValue) {
            return err.value;
        }
        else {
            throw err;
        }
    }
    return self;
}

3 Comentarios:

At 27/7/06 14:21, Anonymous Anónimo said...

me estás diciendo entonces que puedo hacer mis cositas en javascript sin tener que aprender javascript? ¿sabiendo smalltalk me vale? ¿cuando la parte II?, la I me dejó con la miel en los labios...

 
At 16/5/07 02:32, Blogger Unknown said...

Muy interesante Diego!
me gustaría conocer más ejemplos de lo que podría hacerse. Por ejemplo ejemplos de acciones concretas del browser sobre una pagina hecha con un componente seaside serían muy interesantes.

Otra cosa interesante es saber como escala squeak cuando ponés Comet. Tenés experiencias hechas? pruebas de carga?

Creo que hay un errorsillo en el comentario del código donde dice:
"/* En este punto, this apunta a la función y no al receptor. Por eso usamos la variable self apoyándonos en los true-block-closures de JS */"

no debería decir:
"/* En este punto, this apunta a la función y no al receptor. Por eso usamos la variable self apoyándonos en los true-block-closures de ST (Smalltalk)*/" ?

gracias y saludos

Sebastian Sastre
PD: seguí escribiendo tus cosas que es muy interesante!!

 
At 19/12/07 11:45, Anonymous Anónimo said...

hi

It will be very interesting if you submit your explanation in english.

The subject interest me a lot but i am unable to understand spanish.

But it seems to be a Great work !

 

Publicar un comentario

<< Principal