Supporting modularization in textual DSL development

4 downloads 3669 Views 280KB Size Report
Abstract. A domain-specific language DSL provides a ... implementation of a set of domain specific textual .... script for connecting to the first available server, in.
IEEE International Conference of the SCCC. Antofagasta, Chile. November 2010.

Supporting modularization in textual DSL development Jerónimo Irazábal and Claudia Pons LIFIA, Facultad de Informática, Universidad Nacional de La Plata UAI, Universidad Abierta Interamericana Buenos Aires, Argentina [jirazabal, cpons]@lifia.info.unlp.edu.ar

Abstract A domain-specific language DSL provides a notation tailored towards an application domain. The closer the language is to their target domain, the more useful the language is for developers. But this increment in the level of specificity raises the issue of duplication of concepts among different languages, and leads to the definition of a family of languages. Despite the advance in tool support for defining the abstract and concrete syntaxes of DSLs, developing a family of DSLs still requires a significant amount of duplicated effort. In this work we present an infrastructure for implementing families of textual DSLs. We introduce a technique based on XText that reduces the effort required to create editors and interpreters by enabling the modularization of the common features and the smooth specification of variability between the DSLs.

1. Introduction A domain-specific language (DSL) is a programming or specification language that offers, through appropriate notations and abstractions, expressive power focused on, and usually restricted to, a particular problem domain [1]. As such, a DSL can be used to generate members of a family of systems in an application domain. These languages are used to reduce the complexity arising when developing software systems using general-purpose languages; a DSL contains a relatively small number of constructs that are immediately identifiable to domain experts and allow developers to construct concise programs capturing the

behaviour of the system at an appropriate level of abstraction. Textual DSLs are generally implemented using standardized infrastructure, such as XText [2] that provides a set of facilities to describe the different aspects of a textual language. Based on that information XText builds a full implementation of that language: the editor, the parser, the type-safe abstract syntax tree, the serializer and code formatter, the code generator or interpreter, etc. The closer the language is to their target domain, the more useful the language is for developers. But this increment in the level of specificity raises the issue of duplication of concepts among different languages. In some cases, very similar DSLs have been developed to target similar problems within slightly different domains (e.g., the DSLs defined in [3] and [4]). The existence of similarities among those languages leads to the definition of a family of languages. Despite the advance in tool support for defining the abstract and concrete syntaxes of DSLs, developing a family of DSLs still requires a significant amount of effort and expertise. In such cases, for each language of the family the abstract and concrete syntaxes should be specified, as well as supporting infrastructure, such as editors, analysers, or code generators should be individually implemented. Implement repeatedly each language from scratch not only is inefficient, it is also prone to errors. All DSLs in a family share a common core and show specific variations that are propagated in a predictable manner to syntax, semantics, and tool support. To increase efficiency and reduce errors, the following challenges must be addressed: - Systematic reuse of DSL constructs and infrastructure. A reuse mechanism that goes beyond

IEEE International Conference of the SCCC. Antofagasta, Chile. November 2010.

simple copy&paste and covers all aspects of a DSL's infrastructure (grammars, editors, parsers, interpreters, compilers) is required. - Systematic support for specifying variability between the DSLs. The specification of differences between the DSLs should be easily handled. In this work we present an infrastructure for implementing families of textual DSLs. We introduce a technique based on XText that enables the modularization of the common features and the specification of variability between the DSLs by the definition of a specialization language. Editors are reused all over the family. Additionally each family is equipped with a generator that automatically generates specific interpreters by exploiting the information in the specialization file. The rest of the paper is organized as follows. In Section 2 we describe the schema that we propose for the implementation of textual DSL families using Xtext. In section 3 we apply this schema to the implementation of a simple family of imperative languages. In section 4 we discuss related works

and finally in section 5 we present the conclusions and lines of future work.

2. Implementation Schema for Textual DSL Families In this section we define a scheme for the implementation of a set of domain specific textual languages conforming a family (that is to say, a set of languages that share a number of common features as well as a number of well-identified variations among them). This proposal makes it possible to avoid the replicated effort of developing specific tool support for each member of the family. The schema is based on XText which is the most popular infrastructure for the implementation of individual textual languages in the field of model driven development. This proposal focuses on implementation issues. It is out of its scope the definition of mechanisms for identifying families and/or discovering commonalities and variability. Figure 1 displays the structure of the proposed schema.

Figure. 1. Scheme for the implementation of families of textual DSLs .

IEEE International Conference of the SCCC. Antofagasta, Chile. November 2010.

This scheme identifies different roles: -

-

-

The DSL expert. This is a person with expertise in language engineering and with knowledge in the whole domain of the family. She/he is responsible for formalizing the definition of the family by identify common aspects and variation points. The DSL developer. This is a person with expertise in one of the specific domains within the family. She/he is responsible for building a particular member of the family. The DSL user. This person needs no expertise in language engineering. She/he is a programmer with knowledge in a single textual language.

The main responsibilities of each role are as follows: 1.

2.

3.

DSL Expert responsibilities: - To define the grammar of the Core language (using XText). - To define the grammar of the specialization language (using XText). - To automatically generate the Core editor from the grammar (using XText). - To automatically generate the Specialization editor from the grammar (using XText). - To build the interpreter generator, that is a transformation that produces an interpreter for each family member from the corresponding specialization file. DSL Developer responsibilities: To create and individual DSL by writing a specialization file (using the specialization editor). - To automatically build the DSL interpreter (by running the interpreter generator with the specialization file as input). - To manually complete the DSL interpreter, if required (the fully automatic generation of the interpreter might be unfeasible, depending on the complexity of the family). DSL User responsibilities: - To write a program (core file) using the DSL.

After performing the steps one and two, described above, we count with an editor (the same for all the

family members) and with a specific interpreter for the specific member of the family. Such interpreter can be incorporated into a complex application by an application developer or simply executed by a script. Below we describe the context of use, advantages and limitations of the proposed scheme: We recommend using this scheme when: - You need to build editors and interpreters for textual languages belonging to a family of languages and you need to invest little effort. - You can use the same editor and syntax for all languages into the family. The limitations are: - All the languages in the family should use the same editor. - Validations that are specific of each language cannot be defined in the core and should be specified with the specialization language. The main advantages are: - Editors and interpreters are reused across the family. - There is a clear separation between the core (shared) concepts and the specific concepts. - The schema takes advantage of well know infrastructure for textual DSL development. An important point within the schema is the following. The transformation that automatically generates the interpreter for each family member has a segment that does not depend on the specific language, but on the family. In the next section we show an example of the application of the schema and present a number of implementation alternatives.

3. Applying the schema to a simple family In this section we apply the proposed schema to the implementation of a simple family of imperative languages. As expected the constructs of these languages are variable declarations, conditional branch and iteration, among others. Additionally,

IEEE International Conference of the SCCC. Antofagasta, Chile. November 2010.

each language manipulates its own entities. Entities display behavior encapsulated into operations. To build this DSL family, the DSL expert should in first place identify the commonalities of the family and describe them through the core language. Figure 2 shows the heading of the Core language grammar. grammar ar.edu.unlp.info.lifia.Script with org.eclipse.xtext.common.Terminals import "ar.edu.unlp.info.lifia.ScriptCont ext" as domain generate script ar.edu.unlp.info.lifia.Script Figure 2. Heading of the Core language grammar Then, the DSL expert should recognize the variability points of the family and specify them through the specialization language. Figure 3 displays the heading of the Specialization language grammar. Notice the connection between both declarations. grammar ar.edu.unlp.info.lifia.ScriptConte xt with org.eclipse.xtext.common.Terminals generate scriptContext ar.edu.unlp.info.lifia.ScriptConte xt Figure 3. Heading of the Specialization language grammar The grammar of the Core language consists of a set of standard imperative constructs that assume the existence of entities equipped with operations. The core language contains no detail about these entities (it only assumes that entities exist). Each member of the family will manipulate a particular kind of entity whose features are declared through the specialization language. Figure 4 shows some of the Core grammar rules. The first rule states that a Script consists of three sections: - The section named domain contains the reference to the specialization file where the specific entities are declared. This

syntactic constructs allows us to import the specialization file into the core file. - The next section contains a list of variable declarations. Notice that variables can be declared using the specific domain types. - The last section contains imperative statements, such as variable assignment and iterations. Notice that an expression can contain the invocation to an operation of any specific domain entity. Script: domain=Domain (variables+=VarDecl)* statement=Stat?; Domain: ';';

'domain'

VarDecl: 'var' type=Type ';'; Type: SimpleType EntityType;

importURI=STRING name=ID |

':'

List

|

EntityType: entity=[domain::Entity]; Stat: VarAssign| If |While |ForEach |Expression | Block |Wait |Break; … CallOp: op=[domain::Operation] '('(expressions+=Expression (','expressions+=Expression)*)?')' ; Figure 4. Part of the Core language grammar Then, figure 5 shows the Specialization grammar rules. In this case the specialization language is quite simple. It consists of entity declarations. Each entity is defined by a name and a set of operations with parameters. ScriptContext: (entities+=Entity)*; Entity: 'entity' name=ID '{' operations+=Operation* '}'; Operation: static?='static'? name=ID '('(parameters+=Parameter (','parameters+=Parameter)*)?')'

IEEE International Conference of the SCCC. Antofagasta, Chile. November 2010.

(':' type=Type)? ';'; Parameter: name=ID ':' type=Type; Figure 5. Specialization language grammar Once the grammars are defined, the DSL expert should write the transformation that generates an interpreter for each member of the family. This transformation contains a generic fragment that represents the common features of the family members. This segment contains the main logic of the interpreter. Then the specific semantics of each language should be manually specified by the DSL developer. In our scheme, the generic part is implemented by a Java class named Interpreter. This class should be integrated into a specific application and can be used in the following way: (new Interpreter()).interprete(fileToIn terprete);

The part of the Interpreter that reflects the features of the specific language consists in the generation of a Java class for each entity as specified in the specialization file. This part of the transformation is trivial. To illustrate, at the end of this section we display the Java class generated from an entity. Then, by using reflection, the interpreter delegates to the classes that were generated from the entities. Let us describe the Interpreter in detail: The Java classes created by Xtext should be imported: import ar.edu.unlp.info.lifia.script.*;

The class Interpreter exposes interpreting statements from files: public void path) {…} public void resource) {…}

methods

for

interprete(String interprete(Resource

A hashtable is used for storing the values of the variables:

private Hashtable localState;

The interpretation of a Block consists in interpreting the set of instructions inside it: private void interpreteBlockStat(Block block) { for (Stat stat : block.getStatements()) { interpreteStat(stat); } }

The interpretation of a conditional branch consists in first evaluating the condition and then evaluating the corresponding branch. private void interpreteIfStat(If ifStat) { if ((Boolean) interpreteExpression(ifStat.getCon dition())) { interpreteBlockStat(ifStat.g etThen()); } else { interpreteBlockStat(ifStat.g etElse()); } }

The interpretation of the rest of the imperative constructs is as usual, except for the interpretation of the CallOp expression that is achieved by delegating the invocation to a method in the corresponding Java Class, assuming its existence. Now, after the editor and the interpreter generator were created, it is time for the DSL Developer to create a specific member of this family. She/he will use the Specialization language editor to create a specialization file such as the following one: entity Server {

IEEE International Conference of the SCCC. Antofagasta, Chile. November 2010.

static getServers() [Server]; available() : Boolean; connect(); }

:

This file describes a single entity with 3 operations. By running the interpreter generator on this file we obtain two Java classes: a class representing the Interpreter that we described above and other class representing the entities, named EntityServer.java. Then, the DSL developer should manually complete the semantics of the operations of the Server entity: public class EntityServer { public static Collection getServers() { //TODO Implement this method }; public Boolean available() { //TODO Implement this method }; public void connect() { //TODO Implement this method }; } At this point the implementation of the DSL is finished. Now, the DSL user can write a program using the DSL. For example she/he can write a script for connecting to the first available server, in the following way: domain "Server.ctx"; foreach Server.getServers() { if (current.available()) { current.connect(); break; } } In this way we have completed the development of a simple but expressive example going throughout the proposed schema for the implementation of a family of textual domain specific languages.

4. Related work For many years we have been using a variety of tools for the development of textual DSLs [5, 6]. However, in recent years there was renewed interest in the use of textual DSLs in the context of modeldriven development. Here, a textual DSL is typically developed using XText. These approaches focus on the manual development of a single DSL. In contrast, the approach presented in this paper aims to support the development of families of languages by modularizing and reusing the commonalities of the family members. The work most closely related to our proposal is presented by Zschaler et al. in [7]. These authors introduce the concept of domain-specific metamodelling language which codifies recurring patterns and commonalities across a set of DSLs and provides a mechanism for expressing the variations. In this case, each member of the family has its own syntax and semantics, but all of them share a set of common properties. Our proposal has the same aim, but our notion of sharing is deeper due to the fact that all the family members have the same core grammar. So the syntactic differences are smaller. In fact, the generated editor is the same for the entire family. Each member imports its own specialization file which introduces the syntactic particularities of each language. This homogeneity is good in cases where the same developer uses more than one language in the family and also for interoperability reasons. Other interesting recent work on the definition of DSLs families was presented by Obber et al in [8], addressing interoperability between various members of a family of DSLs. The approach consists in applying results of the category theory in order to merge the languages into a unification one, automatically obtained. This work is different to ours in the sense that the family is built following a button-up approach while our proposal runs topdown.

5. Conclusions and future work In this paper we have proposed a scheme for implementing families of textual languages. This schema enables the sharing of common features in the family and the systematic reuse of language constructs and infrastructure elements (such as editors and interpreters). Additionally, the scheme has been designed with the aim of taking advantage

IEEE International Conference of the SCCC. Antofagasta, Chile. November 2010.

of tools that are currently used by the MDD community for the construction of individual textual languages, in particular XText. As future work we are evaluating the scalability of the proposal to the implementation of more complex families. Currently all the family members share a unique specialization language (each member defines its particularities by declaring a specialization file written in such specialization language). But, complex families - requiring more than one specialization language - may possibly exist. Also, additional levels of specialization could be incorporated to the scheme. Another important feature that should be evaluated is the impact of changes in parts of the scheme. For example, how changes in the core or in the specialization language propagate to the syntax, semantics and tool-support of the family members.

6. References [1] van Deursen, A., Klint, P., Visser, J.: Domain-specific languages: an annotated bibliography. ACM SIGPLAN Notices,35- 6_:26–36. (2000). [2] Xtext - Language Development Framework http://www.eclipse.org/Xtext/ Visited in Jun 2010. [3] Nikolaos Drivalos, Dimitrios S. Kolovos, Richard F. Paige, and Kiran J. Fernandes. Engineering a DSL for software traceability. In 1st Int' Conf. on Software Language Engineering (SLE 2008), Revised Selected Papers, pages 151-167. Springer-Verlag. (2009). [4] Steffen Zschaler, Pablo Sanchez, Joao Santos, Mauricio Alferez, Awais Rashid, Lidia Fuentes, Ana Moreira, Joao Araujo, and Uira Kulesza. VML* a family of languages for variability management in software product lines. In Proc. 2nd Int' Conf. on Software Language Engineering (SLE'09) (2009). [5] Arie Deursen and Paul Klint. Little languages: Little maintenance? Journal of Software Maintenance, 10:75-92. (1998). [6] Lloyd Nakatani and Mark Jones. Jargons and infocentrism. In 1st Acm SIGPLAN Workshop on Domain-Specific Languages. (1997). [7] Stephen Zschaler, Dimitrios S. Kolovos, Nikolaos Drivalos, Richard F. Paige, and Awais Rashid Domain-Specific Metamodelling Languages for Software Language Engineering. Software Language Engineering Conference (SLE). Denver. USA. Oct. 2009. Lecture Notes In Computer Science;. SpringerVerlag Berlin, Heidelberg. (2009). [8] Ileana Ober Ali Abou Dib Louis Féraud, Christian Perceboi. Towards Interoperability in Component Based Development with a Family of DSLs. Lecture Notes In Computer Science; Vol. 5292. Proceedings of the 2nd European conference on Software

Architecture. Pages: 148 - 163 . Springer-Verlag Berlin, Heidelberg. (2008)