Angel "Java" Lopez

NET, Java, PHP y Desarrollo de Software

This Blog

Syndication

Search

Tags

Community

Email Notifications

Archives

.NET

ASP.NET

Windows Form

VB.NET

C#

Sitios

Blogs

Presentando AjSoda

Hace un año, escribí un post, comentando el trabajo de Ian Piumarta work:

Self-sustaining sysmtes, Cola, Pepsi y Mate

Proponía que una implementación de las ideas Ian Piumarta y Warth, era posible en .NET o en Java. En vez de usar C como lenguaje base, se podría implementar todo sobre un lenguaje con máquina virtual, con un framework rico de clases de base, y con un garbage collector automático. Para mí, era una interesante idea, que merecía algo de atención.

Para entender las ideas ideas de Piumarta y Warth, lean lo que describieron sobre una implementación mínima en:

http://piumarta.com/pepsi/objmodel2.pdf
http://piumarta.com/pepsi/objmodel.pdf

Encontrarán el código de una implementación en C, en esos papers. Un diagrama aclaratorio:

(tomado deOpen Extensible Dynamic Programming Systems Dls )

Esta semana pasada, puse manos a la obra, y estuve trabajando en una implementación en C# de esas ideas. Publiqué mi código en my  Proyecto Google Code AjCodeKatas, dentro de:

http://code.google.com/p/ajcodekatas/source/browse#svn/trunk/AjSoda

La solución tiene cuatro proyectos (dos librerías de clases, y otros dos que son sus respectivos tests). El proyecto principal es el AjSoda:

 

Un diagrama de las interfaces principales:

IObject es la interfaz que escribí para representar un objeto genérico. Tiene un "payload", que es un arreglo de referencias a objectos .NET arbitrarios.

Una alternativa que consideré, era apuntar solamente a IObjects. Pero quiero tener la capacidad de apuntar y manipular directamente objetos .NET (u objetos Java, si lo reimplemento en ese lenguaje). La alternativa hubiera sido apuntar solo a IObjects, e implementar un digamos DotNetWrapper : IObject que encapsulara los accesos a un objeto .NET (algo así está armado en el AjBasic).

El método más importante en  IObject es Send. Usando este método, podemos enviar un mensaje (selector y argumentos) a cualquier instancia de IObject.

IBehavior es mi implementación de lo que Piumarta y Warth llaman una vtable (me recuerda a las tablas de métodos en viejas implementaciones de C++). Es un objeto que contiene una lista por nombre de métodos que pueden atender los mensajes que se envía a un  IObject.

Cada IObject tiene una propiedad Behavior que apunta a un IObject. Podría haber elegido apuntar a un IBehavior, pero de esta manera, el Behavior de un objeto puede ser reemplazado por cualquier otro objeto que entienda un mensaje con selector #lookup:.

No necesité hasta ahora, implementar el concepto de Closure, como lo describen Piumarta y Warth en su paper. Usando closures, ellos implementan slots a la Javascript o Self. Pero en los experimentos que hice, no necesité aún implementar eso.

Las clases principales de implementación son:

Cada BaseObject implementa un IObject, manteniendo un arreglo interno de objetos como "payload" del objeto:

public class BaseObject : IObject { private object[] values; public BaseObject() { } public BaseObject(int size) { this.values = new object[size]; } public int Size { get { if (this.values == null) { return 0; } return this.values.Length; } } public IObject Behavior { get; set; }

(Noten que la propiedad Behavior es un IObject, por las razones que expliqué antes).

El método más interesante es el Send:

 

public virtual object Send(string selector, params object[] arguments) { if (selector == null) { throw new ArgumentNullException("selector"); } if (this.Behavior == null) { throw new InvalidOperationException("No behavior in object"); } IMethod method = (IMethod) this.Behavior.Send("lookup:", selector); if (method == null) { throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture, "Unknown message '{0}'", selector)); } return method.Execute(this, arguments); }

No uso directamente this.Behavior.Lookup para obtener el IMethod asociado a un selector. En cambio, uso directamente el método Send para enviar un mensaje al object apuntado por Behavior. De esta forma, obj.Behavior puede ser dirigido a cualquier objeto IObject que quiera implementar la lógica de lookup de un método por selector. Esta decisión tiene impacto en el rendimiento, pero permite explorar nuevas estrategias de obtención de métodos. Pueden leer en los papers mencionados, cómo implementan herencia múltiple y Traits, usando esta capacidad de redefición de lookup.

AjPepsi

En el código encontraran un proyecto adicional, AjPepsi, donde implementé un parser, y intérprete de bytecodes, de un lenguaje parecido al que usaron language Piumarta/Warth como prueba de concepto en sus escritos. Acepta código como:

Object new [^self class basicNew initialize] Object initialize [] List : Object(head tail) List head [^head] List tail [^tail] List head: newHead [head := newHead] List tail: newTail [tail := newTail] list1 := [^List new] list2 := [^List new] [list1 head: 'Hello'] [list2 head: 'World'] [list1 tail: list2]

Object y List son prototipos. Dejaré una explicación más detallada de este lenguaje y su implementación para un futuro post. AjPepsi aún está en desarrollo; probablemente, refactorearé gran parte del núcleo de la implementación. Tomé el código de AjTalk como base, pero no estoy seguro de haber tomado la decisión correcta: AjPepsi es muy orientado a prototipos, y basado en AjSoda, así que tuve que trabajar bastante para llevarlo a estas ideas.

Una gran "feature" pendiente: generar código C# a partir del estado de la máquina virtual (clases, métodos  e instancias). Vean en el sitio de Piumarta cómo implementó un compilador de su propio lenguaje en C, y que genera en ese lenguaje el código de su propio intérprete. De ahí la idea de "lenguajes auto sustentables".

Los tests están en verde:

El "code coverage" es bueno:

Hay algún "code smell" para refactorear. Un ejemplo clásico: el gran switch con toneladas de código en el intérprete de byte code. Pero la mayoría de ese código oloroso está en el proyecto AjPepsi. AjSoda está tomando forma, yendo hacia una versión estable. Me tomó sólo 4 horas escribir el código de AjSoda, pero estoy gastando muchas horas escribiendo AjPepsi (10 horas hasta ahora).

Como de costumbre, ¡me divertí escribiendo este código!

Más enlaces sobre las ideas de Piumarta/Warth:

http://lambda-the-ultimate.org/node/2483
http://piumarta.com/
http://piumarta.com/pepsi/pepsi.html
http://piumarta.com/software/cola/

Comentarios, sugerencias, bienvenidos.

Nos leemos!

Angel "Java" Lopez
http://www.ajlopez.com/
http://twitter.com/ajlopez

Published Mon, Jan 26 2009 8:46 by lopez

Leave a Comment

(required) 
(required) 
(optional)
(required) 
If you can't read this number refresh your screen
Enter the numbers above: