AjTalk en C# (3) Environments

Published on Author lopezLeave a comment

Anterior Post 
Siguiente Post 

Hace unas semanas, agregué el soporte de environments (ambiente, entorno) a mi proyecto de código abierto AjTalk, una máquina virtual Smalltalk escrita en C# (hay otras versiones, en Java y en JavaScript). ¿Qué es un environment en mi jerga? Es un diccionario, donde puedo guardar artefactos por nombre, un directorio. Por ejemplo, para guardar clases por nombre. La variable global Smalltalk es un environment clásico. Pero en un Smalltalk clásico, todas las clases definidas van a parar a ese diccionario global, lo que puede dar lugar a colisión de nombres. La forma normal de solucionar (p.ej. en Squeak y Pharo) es agregarle un prefijo (de dos letras) a cada clase de nuestra librería. Pero yo quiero tener el soporte de tener otros environments, como pasa con los namespaces de .NET o los package de Java. Smalltalk clásico también tiene los llamados pool dictionary, pero hasta donde sé, son para usar desde una clase y sus derivados. Yo quiero tener la noción de paquete: todas estas clases se ven entre sí, pero no están en el environment del tope, en Smalltalk, sino en un environment dedicado a mi librería. Agregué una implementación inicial, con estos tests:

https://github.com/ajlopez/AjTalk/blob/master/Src/AjTalk.Tests/AssertTests/EnvironmentTests.st

Al comienzo, verifico que Smalltalk es un ambiente, un environment y es el actual:

"Current environment is Smalltalk"
[Environment current == Smalltalk] assert.

Puedo crear nuevos entornos:

env := Environment new: #MyEnvironment.

Automáticamente, el nuevo entorno se registra/agrega al entorno actual, en este caso, a Smalltalk:

"The new environment was defined as global at Smalltalk"

[(Smalltalk at: #MyEnvironment) isNil not] assert.
[(Smalltalk at: #MyEnvironment) == MyEnvironment] assert.
[(Smalltalk at: #MyEnvironment) == env] assert.

[MyEnvironment isNil not] assert.
[MyEnvironment == env] assert.

Cada nuevo entorno tiene automáticamente una entrada Smalltalk que apunta al original global:

"Dotted expression syntax sugar for MyEnvironment at: #Smalltalk"

[MyEnvironment.Smalltalk == Smalltalk] assert.

Podemos pasar a tener un nuevo entorno actual:

env setCurrent.

"Current environment check"

[Environment current == env] assert.
[Environment current == Smalltalk.MyEnvironment] assert.

Y ahora, la característica principal de lo que quería implementar, de ahora en más, las definiciones de clases (sin cambiar el código de su definición) quedan registradas en el entorno actual:

"Define a class at current env environment, no change to syntax"

Object subclass:#MyClass
    instanceVariableNames:''
    classVariableNames:''
    poolDictionaries:''
    category:''
.

[(env at: #MyClass) isNil not] assert.
[(Smalltalk at: #MyClass) isNil] assert.

Ortogonal a esto de environments, implementé además módulos (algo apareció en el post anterior): una forma de buscar y leer archivos file out, y ejecutarlos dentro de un nuevo entorno. Esto es similar al import de Python, y algo menos parecido, al require de Node.js/CommonJS. Bueno, pero eso es tema para otro post 馃槈

Nos leemos!

Angel “Java” Lopez

http://www.ajlopez.com

http://twitter.com/ajlopez

Leave a Reply

Your email address will not be published. Required fields are marked *