miércoles, febrero 28, 2007

for var f in foes do

No está mal para el típico splash del IDE de pruebas, ¿o no?

Freya: Sharp Blade
Es verdad que la chica tiene cara de enfado. Da la impresión de estar pensando algo así como: "al próximo que me pregunte si Marteens cobra de Microsoft por recomendar .NET le rebano la cabeza"...
He hecho el dibujo aprovechando el paso del IDE de pruebas para Freya, de su primera versión SDI (Hammer, es decir, martillo) a la nueva versión MDI/tabbed pages. Había que darle un nombre, sobre todo para los proyectos no se llamen freya01, freya02 y así hasta el aburrimiento, y ya que teníamos anvil (el yunque), para el editor de código, y el ya mencionado hammer, lo lógico era usar otro artilugio relacionado con los herreros. Nombre elegido: Sharp Blade, es decir, hoja o espada afilada. No está mal... Ya sé que CodeGear nunca reconocerá que mi compilador es mejor que el de ellos, pero al menos podrían contratarme para decidir los nombres de proyectos. Mira que usar nombres de culebras, coño...
... y sí, ya sé que el dibujo tiene fallos: no pienso dedicarme a estas alturas de la vida a las artes gráficas. De todos modos, me sorprende precisamente por eso: de repente "vi" la imagen mentalmente, me senté con mi Xara Xtreme Pro una hora, aproximadamente, y hala, dibujo casi terminado. La chica está dibujada "de memoria", y se parece mucho a una amiga que hace tiempo no veo. El pelo necesita más detalles, y también el labio superior. Ya lo arreglaré cuando vuelva a tener una hora de libertad.
Recuerde: Sharp Blade...

Etiquetas:

martes, febrero 27, 2007

La Cara Oculta de C++... en portugués

BrazilHay sorpresas y sorpresas, y ésta es de las agradables: Thérbio, un programador de Brasil, ha contactado conmigo para obtener el permiso y traducir al portugués mi libro sobre La Cara Oculta de C++ Builder 4. Por supuesto que he accedido: más bien considero un honor que el libro siga despertando interés, y he puesto todo lo necesario para facilitar la tarea.
El proyecto se coordina desde este foro:
Como se trata de un libro de 1998/99, voy a proponerles también añadir parte del material sobre el API de Windows que he incluido en Intuitive Delphi: objetos del núcleo, manejos de hilos, etc... aunque primero tendré que traducir el código y los ejemplos de Delphi a C++ Builder. Por supuesto, cualquier adición a la versión en portugués se reflejará en la versión en castellano.

Etiquetas: , ,

viernes, febrero 23, 2007

Renovación de la suscripción MSDN

Me tocaba renovar este mes la suscripción anual a la MSDN, y ya lo he hecho. Me suscribí el año pasado a Visual Studio Profesional, con MSDN Profesional. No es ni remotamente la opción más cara... pero trae todo lo que necesito (por eso lo cuento aquí). El servicio de Microsoft, además, es bueno: todos los meses, religiosamente, llega un mensajero a IntSight con un mogollón de CD's y DVD's de los que, para serle sincero, sólo llego a ver luego uno o dos.
Información que le puede interesar: la compra original me costó alrededor de 1.100 o 1.200 euros. La renovación cuesta unos 800 euros. Es mucho más barato que la cantidad que gastaba anualmente en licencias de Delphi, y lo que obtengo es un producto mucho más completo: incluye toda la suite de lenguajes: Visual C++, C#, VB.NET y JScript, aparte de todo tipo de versiones de desarrollo de SQL Server. De todos modos, le advierto que existe una versión más barata: comprar solamente Visual Studio, sin la suscripción MSDN. Los precios de primer compra están en la zona de los 800 euros, y las actualizaciones salen por unos 500 euros (cito de memoria y muy aproximadamente). De todos modos, si se puede dar el pequeño "lujo" de comprar la Team Server Edition, no se prive. Lo que echo más en falta de mi vesión Profesional es el profiler que viene en las versiones superiores. Pero por suerte, .NET ofrece un API para profilers, y según los artículos que he consultdo, sería relativamente sencillo programar uno si fuese necesario.
Otro dato que le puede interesar: la renovación, al menos, se puede tramitar directamente con Microsoft España, si se quiere pagar con tarjeta. La mayoría de los distribuidores te ponen pegas si quieres pagar por esta vía, pero existe la posibilidad de comprar directamente con un comercial de Microsoft, por teléfono... que fue lo que hice.

Etiquetas:

jueves, febrero 15, 2007

Necesito ayuda

¿Tiene instalado un Delphi.NET? Necesito que me eche una mano; no importa la versión, siempre que sea para .NET. Estoy retocando el diseño de los destructores en Freya, pero no le veo mucho sentido a la idea. Se supone que, con la ayuda de un destructor, se facilitaría la implementación de la interfaz IDisposable.
El problema está en que el patrón de implementación propuesto por Microsoft funciona a través de un método Dispose auxiliar, declarado virtual y protegido, y con un parámetro de entrada de tipo booleano. Esto sirve para distinguir entre las llamadas "explícitas" a Dispose (como las realizadas a través de una instrucción using) de las llamadas automáticas provocadas por el colector de basura. Si no se incluye esta distinción, el destructor pierde la mayor parte de su atractivo, y puede confundir más que ayudar.
¿Qué necesito, en concreto? Si tiene alguna versión de Delphi.NET (la 8, la 2005 o la 2006), me gustaría poder echarle un vistazo a un ensamblado pequeño compilado, preferiblemente como DLL. No me atrevo a escribir código fuente, porque no tengo forma de verificarlo sintácticamente, pero sólo necesito que incluya dos clases: una clase base y una clase derivada de la primera. Cada una de estas dos clases debe tener un destructor. Lo que haga el destructor no tiene importancia: un WriteLine a la consola, por ejemplo. Eso sí, que contengan al menos una instrucción, para que el compilador no haga cosas raras con el destructor.
O, por el contrario, si tiene claro cómo genera Delphi código para destructores en .NET, o ha escrito algún artículo, o conoce dónde hay uno, también me valdría. En este momento no tengo ningún Delphi.NET instalado: sólo mi viejo Delphi 7 "nativo".
... y muchas gracias por adelantado.

Actualización: Javier Bleda me ha dado la URL del blog de Hallvard Vassbotn, y ahí me he encontrado con el enlace a un viejo artículo de Brian Long, donde cuenta los detalles de la técnica.
A primera vista, es así como lo tengo ya implementado en Freya... pero no me convence la idea, para ser sincero: el trabajo que ahorra al programador no es significativo, y complica bastante la clase, al exigir la implementación de un tipo de interfaz, y por la necesidad de mantener el patrón en los descendientes potenciales de la clase. En el patrón oficial propuesto por Microsoft, además, se distingue entre recursos administrados y no administrados, y eso es (a primera vista) casi imposible de automatizar, excepto en circunstancias muy especiales y controladas. De todos modos, voy a pensármelo un poco antes de tomar una decisión.

Etiquetas:

Peephole optimization

Compiler information
La imagen pertenece al diálogo de información sobre la compilación de Hammer, el entorno de pruebas para Freya. Como puede ver, he implementado un peephole optimizer. Esto es: un optimizador que trabaja sobre el código final generado, que en este caso, es el código intermedio de .NET. El optimizador analiza la cadena de códigos ejecutables, en pequeños fragmentos, y aplica ciertas reglas de reescritura preprogramadas. Por ejemplo, un branch to return es un salto incondicional que va a parar a un retorno de método. Estos saltos se eliminan, sustituyéndolos directamente por un retorno de método: así se ahorra espacio, y el tiempo que consumiría el salto.
Para ser justos, el compilador normalmente genera código de buena calidad, de modo que este paso de optimización no produce cambios espectaculares. Además, el código IL no permite muchas transformaciones, al tratarse de la simulación de una máquina de pila. En una máquina de pila, cada operación es, en cierto sentido, insensible a las operaciones que la siguen o preceden; sólo importa el contenido de la pila. De todos modos, ya he detectado unas cuantas oportunidades de mejorar el código en esta parte de la compilación.
En cualquier caso, este módulo era necesario: el generador de código IL que ofrece Reflection.Emit no es gran cosa, pues obliga a indicar explícitamente el tamaño de los códigos de saltos. Si un salto en IL se produce a una instrucción que queda a menos de 127 bytes, se puede usar un código de salto especial para que la instrucción, incluyendo el desplazamiento del salto, quepa en dos bytes. En caso contrario, ocuparía cinco bytes. El generador predefinido no ayuda para nada en la decisión del tamaño del salto. El módulo de optimización de Freya es el encargado de tomar estas decisiones, de manera automática.

Etiquetas: ,

sábado, febrero 10, 2007

Iteración en Freya

¡Ya funcionan los iteradores en Freya! Había postergado la "conexión" del módulo correspondiente, pensando que iba a resultar más complicado, pero al final ha sido muy sencillo.
iterator Stack: X;
begin
for var
i := Count - 1 downto 0 do
yield
Items[i];
end;
El truco principal consiste en recorrer el cuerpo del método iterador buscando parámetros y variables locales. Para cada uno de ellos, se crea un campo para la clase que genera el compilador internamente, y las referencias a variables y parámetros se sustituyen por referencias a los campos correspondientes. Hay que tener cuidado, porque las referencias a campos necesitan empujar antes dentro de la pila la referencia a la instancia de la clase. Un detalle elegante: las referencias a campos de la clase donde se define el iterador son muy fáciles de traducir, porque la referencia a Self se considera también un parámetro del iterador, y como tal, se duplica en la clase enumerable generada por el compilador.
Por supuesto, quedan algunos pequeños detalles por resolver. Por ejemplo, hay que tener cuidado con los iteradores estáticos, como los que se definirían en una sección de implementación anónima, y hay que mejorar los mensajes de error del compilador cuando se escribe una instrucción yield en zonas prohibidas, como la sección finally de un try/finally.
¿Qué tal un ejemplo más complejo? Este es un iterador para recorrer en preorden los nodos de un árbol binario:
iterator PreOrder: Y;
var
St: Stack[TreeNode];
begin
if Root <> nil then
begin

St := new Stack[TreeNode];
St.Push(Root);
repeat
var t := St.Pop;
if t.Left <> nil then
St.Push(t.Left);
if t.Right <> nil then
St.Push(t.Right);
yield t.Value;
until St.Count = 0;
end;
end;
Es interesante ver cómo se traduce el código anterior, según Reflector. El compilador crea una clase privada y anidada dentro del árbol, que implementa la interfaz IEnumerable. Así es como Reflector traduce a C# el código IL generado por el compilador para el método MoveNext:
public sealed override bool MoveNext()
{
switch (this.state$)
{
case 0:
if (this.Self.Root == null)
goto Label_00D1;
this.St = new Stack<BinaryTree<Y>
.TreeNode>();
this.St.Push(this.Self.Root);
break;
case 1:
this.state$ = -1;
if (this.St.Count != 0)
break;
goto Label_00D1;
default:
goto Label_00D1;
}
this.t = this.St.Pop();
if (this.t.Left != null)
this.St.Push(this.t.Left);
if (this.t.Right != null)
this.St.Push(this.t.Right);
this.current$ = this.t.Value;
this.state$ = 1;
return true;
Label_00D1:
this.state$ = -2;
return false;
}
Parece más complejo de lo que realmente es... cuando se intenta traducir del formato IL a un lenguaje estructurado.

Etiquetas:

jueves, febrero 08, 2007

El programa más largo

¿Qué es esto? ¿Más noticias sobre ray tracing? Sí, pero sólo en parte. Es, efectivamente, una imagen producida por un programa de ray tracing, pero el programa ¡está escrito íntegramente en Freya!
Lo que he hecho es traducir el núcleo básico de XSight RT a Freya, buscando errores del compilador, construcciones incómodas para el programador, traducciones ineficientes, y más cosas de este estilo. Los programas que estaba usando como pruebas del compilador no pasaban de dos o tres páginas, y quería probar con un ejemplo más ajustado a la realidad.
En realidad, el programa está empaquetado en sólo 1120 líneas de código, que he agrupado por conveniencia en un único fichero fuente. Puede examinar el fichero siguiendo este enlace:
En la vida real, el código estaría distribuido entre varios ficheros, pero como Hammer maneja de momento sólo un documento por vez, mezclé los ficheros para simplificar la compilación. Cuando Freya esté terminado, utilizará un sistema de proyectos y soluciones muy parecido al de Visual Studio, adicional a las actuales posibilidades del compilador.

¿Qué contiene la prueba, y qué no contiene? La demo puede trabajar con esferas, cilindros y uniones. No he incluído soporte para operaciones de intersección y diferencia, y los materiales son, básicamente, plástico y metal. Claro, el modelo básico ya estaba suficientemente probado con C#, y todo este jaleo me ha llevado menos de un día para escribirlo, probarlo y darle forma definitiva.
¿Y qué tal de velocidad? Primero, una aclaración: la velocidad de XSight RT es similar a la de un ray tracer "nativo", gracias a todo tipo de optimizaciones y a un cuidadoso diseño. En el código de ejemplo en Freya he preferido utilizar construcciones del lenguaje más elegantes que eficientes. Por ejemplo, XSight RT prácticamente renuncia al uso de operadores definidos por el programador, mientras que el ejemplo los utiliza sin reparos. A pesar de ello, los tiempos de ejecución son comparables: un ejemplo que tarda de 80 a 90 milisegundos en XSight RT se genera en Freya en un tiempo que va de 110 a 120 milisegundos.
... aunque también es cierto que el compilador de Freya está especialmente preparado para que genere mejor código que el propio compilador de C#. Ya hablaremos de optimización, en su momento...

Etiquetas: