Intérprete tipo Lisp usando DSS y VPL

Este fin de semana estuve programando algunas primitivas de un intérprete Lisp usando DSS Service Compoenntes. El núcleo del intérprete fue derivado de mi trabajo previo con AjLisp, un intérprete que todavía no publiqué. Escribí el ejemplo usando Visual Studio 2008 con el CTP v2.0 de Microsoft Robotics Developer Studio. El ejemplo está publicado en mi Skydrive como DssLisp.zip.

La solución

Consiste de dos proyectos: una librería de clases llamada AjLisp (una versión revisada de mi intérprete original en VB.NET):

y un proyecto C# de Dss Service, que tiene varios service components implementados:

No tiene manifiesto inicial. El proyecto está pensado para ser usado desde diagramas de Visual Programming Language (VPL).

Varios de estos componentes reciben y retornan una SymbolicExpression, el tipo base de mi intérprete. Veamos por ejemplo, los mensajes del componente Rest, que dada una lista devuelve la misma lista sin el primer elemento:

[DataContract()]
public class ExecuteRequest { [DataMember] public SymbolicExpression Expression; } [DataContract] public class ExecuteResponse { [DataMember] public SymbolicExpression Result; }

Para compilar estos componentes, deben ajustar las referencias y directorios del proyecto DSS (ahora apuntan a mis directorios locales y a mi instalación local de Microsoft Robotics Developer Studio).


Usando VPL


Hay tres programas VPL incluidso en los ejemplos. Usan los componentes compilados de la solución. Tuve un problema con estos programas VPL. No pude ejecutarlos desde la opción de  Run. Hay que usar Build -> Compile as a Service, y ahora, lanzarlos con Run -> Run Compiled Services. Creo que el origen del problema es que al armar el diagrama estoy mapeando mensajes propios, no solamente tipos primitivos o Strings. Para recompilar los diagramas, tienen que ajustar las propiedades en cada proyecto VPL:



El primero,  DssLispVpl1, calcula (first ‘(a b c)):



 


Hay dos componentes LispParser y LispToString, que ayudan a convertir de string a SymbolicExpression y viceversa.


El segundo diagrama es DssLispVpl2:



Usa el componente LispAppend para concatenar dos listas predefinidas como Data.


El tercero es un min intérprete DsspLispInterpreter:



 


Tengo que mejorar el tratamiento de errores. Ahora, si ocurre una excepción, no devuelve un Fault, y encontes se genera una causality, que hace que el programa se interrumpa.


Podría implementar contratos genéricos, y reusarlos en los componentes, por ejemplo, un contrato GenericBinaryOperation.


Problemas


Fallé completamente cuando quise escribir una Activity, para implementar una función Reverse de una lista. La actividad se llamaba a sí misma recursivamente, pero en el código generador retornaba desde la última invocación recursiva, sin pasar por las intermedias. El problema es causado porque en todo ese proceso se utiliza la misma instancia de actividad, y al retornar por una puerta el resultado, TODOS los procesos pendientes de esa actividad están escuchando por esa puerta (eso es lo que veo que pasa). Otra piedra en el camino es que las actividades solo aceptan valores primitivos o string como datos en el mensaje de entrada. Puedo solucionar el problema, generando el código de la actividad, levantando la solución, y cambiando los parámetros que trata de, digamos, string a SymbolicExpression.


Un componente interesante, es el componente Uncons, que retorna DOS expresiones simbólicas en su mensaje de respuesta: dada una lista, retorna su cabeza y su cola. Esos dos miembros de la respuesta pueden ser procesados luego en paralelo en dos ramas del diagrama.


Conclusiones


Como en otros posts y ejemplos, encontré la orquestación de componentes DSS via VPL como algo poderoso e interesante, pero le faltan algunas cosas, como el soporte de un objeto genérico o tipos nuestros. Creo que se puede implementar varias primitivas de lenguajes funcionales y usar a VPL para programar sobre ellas. VPL tendría problemas con la recursividad (o no encontré una forma aceptable de hacerla funcionar). Este ejercicio, podría expandirse a otras ideas:


- Manejar una pipeline/tubería para procesar un mensaje genérico (puedo usar un object como DataMember en un mensaje, siempre y cuando no lo envía a otro Host de DSS)
- Tener balanceo de carga
- Serializar/deserializar objetos entre hosts
- Implementar algún workflow o patrones de integración de aplicaciones usando VPL


Nos leemos!


Angel “Java” Lopez
http://www.ajlopez.com


This entry was posted in 1389, 7337, 7747, 8313. Bookmark the permalink.

Leave a Reply

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


*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>