2009-10-04 12 views
5

Me gustaría conocer buenas estrategias para implementar un lenguaje específico de dominio que debe ejecutarse en al menos 2 idiomas (Java, C#) y probablemente más (Python y posiblemente Javascript).escribiendo un lenguaje específico de dominio portátil

Algunos antecedentes. Hemos desarrollado y desplegado un lenguaje específico de dominio actualmente escrito en C#. Se implementa mediante una serie de llamadas a métodos cuyos argumentos son primitivos de lenguaje común (cadena, doble, etc.), Colecciones (IEnumerable, HashSet, ...) u objetos en una biblioteca específica de dominio (CMLMolecule, Point3, RealSquareMatrix). La biblioteca está bien probada y los objetos tienen que cumplir con un esquema XML implementado estable, por lo que el cambio será evolutivo y administrado (al menos esa es la esperanza).

Esperamos que el lenguaje sea utilizado por una comunidad amplia y parcialmente informatizada, acostumbrada a hackear sus propias soluciones sin control central. Idealmente, la DSL creará un grado de encapsulación y producirá la funcionalidad esencial que necesitan. Las bibliotecas administrarán los algoritmos detallados que son muchos y variados pero bastante conocidos. Hay mucho en común con los requisitos de DSL en Domain-specific languages vs. library of functions.

Agradecería ideas sobre la mejor arquitectura (claramente una vez que se implementa no podemos retroceder fácilmente). Las opciones incluyen al menos:

  • Creación de un IDL (por ejemplo, a través de CORBA). El W3C hizo esto para XML DOM - Lo odié - y parece ser excesivo
  • creación manual de firmas similares para cada plataforma y el mejor esfuerzo para mantenerlas sincronizadas.
  • Creación de un lenguaje analizable (por ejemplo, CSS).
  • programación declarativa en XML (c.f. XSLT). Esta es mi solución preferida, ya que se puede buscar, manipular, etc.

El rendimiento no es importante. La claridad de propósito es

EDIT Se debatió si la aplicación llama a una DSL. Descubrí la introducción de Martin Fowler a las DSL (http://martinfowler.com/dslwip/Intro.html) donde argumenta que las llamadas a métodos simples (o llamadas encadenadas) se pueden llamar DSL. Así que una serie como:

point0 = line0.intersectWith(plane); 
point1 = line1.intersectWith(plane); 
midpoint = point0.midpoint(point1); 

podría considerarse una conexión DSL

+1

Un gran negativo a cualquier idioma expresada en XML. ¿Pretendería que un desarrollador trabaje directamente con el XML o ese sería el formato de almacenamiento/tiempo de ejecución? El tipo que inventó ANT dijo que XML era la opción incorrecta y elegiría de manera diferente si podía cambiar las cosas. – SteveD

+0

@stevendick. Gracias, escuché lo que dices. Personalmente soy un adicto al XML, pero trato de mantener la mente abierta. –

+0

Eche un vistazo a lo que el autor original de ANT tiene para decir: http://web.archive.org/web/20040602210721/x180.net/Articles/Java/AntAndXML.html No siga ciegamente el XML- Paradigma de Golden Hammer. Si va a crear una lectura DSL y escrita por personas reales, considere usar una de las muchas herramientas lindas/analizadores agradables en lugar de XML. Hay muchas buenas herramientas en estos días (como ANTLR) que hacen que esto sea práctico. Escribir lexers/analizadores no es tan doloroso ahora como lo era cuando lex/yacc era lo último en tecnología. –

Respuesta

6

Parece haber cierta ambigüedad en la pregunta entre el idioma y la biblioteca. Los términos "DSL interno" y "DSL externo" son útiles, y creo que se deben a Martin Fowler.

Una DSL "externa" podría ser una herramienta de línea de comandos independiente. Se pasa una cadena de fuente, la analiza de alguna manera y hace algo con ella. No existen límites reales sobre cómo pueden funcionar la sintaxis y la semántica. También puede estar disponible como una biblioteca que consiste principalmente en un método similar a eval; un ejemplo común sería construir una consulta SQL como una cadena y llamar a un método execute en una biblioteca RDBMS; no es un patrón de uso muy agradable o conveniente, y horrible si se disemina por un programa a gran escala.

Una DSL "interna" es una biblioteca que está escrita de tal manera que aprovecha las peculiaridades de un lenguaje de host (general) para crear la impresión de que un nuevo idioma puede integrarse dentro de uno existente. En los lenguajes sintácticamente ricos (C++, C#) esto significa usar la sobrecarga del operador de manera que estire (o ignore) seriamente los significados usuales de los símbolos del operador. Hay muchos ejemplos en C++; algunos en C# también: el Irony parser toolkit simula BNF de una manera bastante restringida que funciona bien.

Finalmente, hay una biblioteca antigua simple: clases, métodos, propiedades, con nombres bien elegidos.

Una DSL externa le permitiría ignorar por completo los problemas de integración entre varios idiomas, ya que la única parte similar a una biblioteca sería un método eval. Pero inventar su propia cadena de herramientas no es trivial. La gente siempre olvida la gran importancia de la depuración, intellisense, resaltado de sintaxis, etc.

Una DSL interna es probablemente una tarea inútil si quieres hacerlo bien en C# y Java. El problema es que si aprovecha las peculiaridades de un lenguaje de host, no necesariamente podrá repetir el truco en otro idioma. p.ej. Java no tiene sobrecarga del operador.

Que deja una vieja biblioteca simple. Si desea abarcar C# y Java (al menos), entonces está algo atrapado en términos de una elección del lenguaje de implementación. ¿De verdad quieres escribir la biblioteca dos veces? Una posibilidad es escribir la biblioteca en Java y luego usar IKVM para realizar una compilación cruzada con ensamblados .NET. Esto le garantizaría una interfaz idéntica en ambas plataformas.

En el lado negativo, la API se expresaría en las características de denominador común más bajo, es decir, las características de Java :). Sin propiedades, solo métodos getX/setX. Manténgase alejado de los genéricos porque los dos sistemas son bastante diferentes en ese sentido. Además, incluso la forma estándar de denominación de métodos difiere entre los dos (camelCase frente a PascalCase), por lo que un grupo de usuarios podría oler a una rata.

+0

@Earwicker +1 descripción muy útil. La participación de Java y C# es un hecho (desafortunado). Definitivamente intentaré con IKVM. No me importa perder propiedades y los genéricos son simples. La convención de nomenclatura se puede automatizar, espero. Soy consciente de los problemas de inventar mi propia cadena de herramientas y este es un resumen útil. –

+0

Sí, sin duda podría escribir una herramienta que corrija la convención de nomenclatura. Incluso podría hacer algo similar para las propiedades: busque pares de métodos getX/setX (aunque tal vez sea necesario un marcador de atributos ya que no todos los métodos getX son adecuados para la sintaxis de propiedades, por ejemplo, a veces tienen efectos secundarios visibles). –

+1

@Earwicker. Esta es mi idea actual. Reduzca las llamadas a un subconjunto común de tantos idiomas como sea posible (por ejemplo, no use propiedades, ciertamente no sobrecarga del operador). –

1

capacidad de escapar a la lengua implementación en el caso de que tenga que hacer algo que simplemente no es compatible con su DSL o por razones de rendimiento (Aunque me doy cuenta de que no es una prioridad).

Estoy investigando DSL para implementar reglas en un motor de reglas en C#, algunas de las reglas son realmente complejas y pueden cambiar significativamente en el futuro, por lo que poder escapar a C# es realmente útil. Por supuesto, esto rompe la compatibilidad multiplataforma, pero en realidad es solo una forma de piratear las cajas de borde sin tener que cambiar su DSL.

+1

@Dale. ¡Sí!Habrá casos extremos y no hay ninguna razón por la cual no deban acrecerse de esta manera y luego posiblemente abstraerse y generalizarse más adelante. Esperaría que las principales funciones de la biblioteca quedaran expuestas de modo que no tendríamos una única puerta de enlace. –

0

Usted estaría mejor fuera de la escritura de la biblioteca en C (o algún lenguaje como rpython que generará código C) y luego utilizando el TRAGO o similar a generar los enlaces específicos de idioma para C#, Java Python, etc.

Tenga en cuenta que este enfoque no ayudará si está utilizando Javascript en el navegador: tendrá que escribir la biblioteca de JavaScript por separado. Si está utilizando javascript a través de Rhino, entonces solo podrá usar los enlaces de Java.

0

Es posible interpretar JavaScript desde dentro de un programa Java directamente utilizando el motor de script, y aparentemente también desde C#. Python se puede ejecutar en la JVM y el motor .NET.

Le sugiero que investigue estas opciones y luego escriba su biblioteca en un subconjunto común de las rutas de ejecución disponibles para el idioma que elija. No consideraría escribirlo en un idioma que requiera traducción y conversión posterior, ya que introduce un paso que puede ser muy, muy difícil de depurar en caso de problemas.

2

Aunque no quiero promocionar mucho mi propio proyecto, me gustaría mencionar PIL, a Platform Independent Language, un lenguaje intermedio en el que he estado trabajando para permitir el soporte de múltiples plataformas de software (como Java, Python, ...) , específicamente para DSL externas.La idea general es generar código en PIL (un subconjunto de Java), que el compilador PIL puede traducir a uno de muchos otros lenguajes, actualmente solo Java o Python, pero se agregarán más en el futuro.

Presenté un artículo sobre esto en la conferencia de Software and Language Engineering hace 2 días, puede encontrar un enlace a la publicación del sitio web de PIL (pil-lang.org), si le interesa.

+0

He intentado este tipo de cosas hace algunos años y es útil ver a la gente haciéndolo bastante mejor. –

3

Si está dispuesto a volver a describir su idioma utilizando ANTLR, puede generar su intérprete DSL en varios idiomas sin tener que mantenerlos manualmente, incluidos todos los idiomas que ha mencionado y más.

Antlr es un generador de analizador sintáctico/lexer y tiene una gran cantidad de idiomas de destino. Esto le permite describir su idioma una vez, sin tener que mantener copias múltiples de él.

Consulte toda la lista de idiomas de destino here.

+0

Me gusta esta idea personalmente. Por supuesto, es un gran salto y es difícil retirarse de –

+0

Es cierto que hay una curva de aprendizaje con Antlr y StringTemplate. Pero personalmente, me encanta. Cada vez encuentro más problemas que pueden resolverse con una gramática simplemente descrita. En última instancia, el tiempo que pierde en el proceso de conversión lo compensará con creces con los ahorros de mantenimiento. –

0

Me gustaría ampliar la respuesta de Darien. Creo que ANTLR trae algo a la mesa que algunas otras herramientas lexer/analizador proporcionan (al menos que yo sepa). Si desea crear una DSL que finalmente genere código Java y C#, ANTLR realmente brilla.

antlr proporciona cuatro componentes fundamentales:

  • lexer Gramática (romper las corrientes de entrada en tokens)
  • Analizador de gramática (organizar las fichas en un árbol de sintaxis abstracta)
  • árbol Gramática (repaso la sintaxis abstracta árbol y canalizar los metadatos en un motor de plantillas)
  • StringTemplate (un motor de plantillas basado en principios de programación funcional)

Sus gramáticas lexer, analizador y árbol pueden permanecer independientes de su lenguaje generado final. De hecho, el motor StringTemplate admite grupos lógicos de definiciones de plantilla. Incluso proporciona herencia de interfaz de grupos de plantillas. Esto significa que puede hacer que terceros utilicen su analizador ANTLR para crear, por ejemplo, python, ensamblado, c, o ruby, cuando todo lo que inicialmente proporcionó fue salida java y C#. El idioma de salida de su DSL puede ampliarse fácilmente a medida que los requisitos cambian con el tiempo.

Para obtener el máximo provecho de antlr que tendrá que leer el siguiente:

The Definitive ANTLR Reference: Building Domain-Specific Languages

Language Implementation Patterns: Create Your Own Domain-Specific and General Programming Languages

Cuestiones relacionadas