• No results found

Several modern approaches to software development are language-driven in the sense that they focus on the importance of languages and their systematic creation and use. Favre [49, 50] proposes two new fields of research for the systematic study and engi- neering of languages: Software Linguistics and Software Language Engineering. Gener- ative Programming [34, 35] divides the software development process into two stages: domain engineering and application engineering. Languages are created during domain engineering and used during application engineering. Software Factories [62] is a gener- ative approach where languages are used to describe the variations in product families. The approach is neutral with respect to methodology and process and can be seen as a contribution to these areas.

Model Driven Development [104,151] aims at generating executable code by the step- wise transformation of models that are typically expressed using visual languages. Model Driven Architecture (MDA) can be seen as a particular realisation of Model Driven De- velopment around a set of technologies that were developed in the context of the Unified Modelling Language (UML) [13], in particular Meta Object Facility (MOF) [129]. Clark et al. propose meta-modelling as a foundation for language driven development and dis- cuss syntax and semantics based on meta-modelling [30].

Several model-driven tools exist that generate code for the .NET and Java platforms [26]. Intentional Software [149] focuses on technologies for creating and integrating lan- guages with natural notations, so do several other approaches to language extension [182]. Tools for language prototyping focus on generating programming language implementa- tions from higher-level specifications [41]. Language workbenches [43, 94, 105] are tools for systematically creating languages and development environments.

Many of the existing tools and frameworks mentioned above are rather large and com- plex. One aim of the work presented in this thesis is to provide simpler, more lightweight tooling based on an extensible core of pattern functionality. This is eminent in all three tools that will be presented in the following chapters. Based on a core of pattern function- ality, Concat provides means for parsing, programming, meta-programming and is highly extensible. Similarly, XMF uses a small pattern core for defining schemas, transforma- tions, querying, views and even constraints. In CFR, analysis and scenario specification is based on just three concepts derived from the pattern approach.

The STEPS project [96] undertaken by Kay et al. takes the question of how large software systems need to be literally. The goal is to build a complete personal computer operating system with applications in under 20.000 lines of source code. The systematic use of languages and tools for creating and relating languages is the fundamental approach that underlies this endeavour.

Concat and CFR (Channel Filter Rule Language) provide means to build or analyse systems in layers of languages. The notion of language layering is propagated in several other works. Graham advocates a bottom-up approach in which new languages are created incrementally inside a host-language using existing languages – with the user interface of the system forming the topmost language layer [61]. Language-oriented programming [177] on the other-hand propagates a “middle-out” approach where development starts with the definition of a domain-specific language that forms the middle-layer that links an application with an implementation language.

Domain Specific Languages (DSLs) [55] are a topic of growing research interest and questions such as how to create, maintain, and integrate languages are studied in the context of DSLs. In the Lisp community, the idea of developing specialised languages that are embedded in Lisp is widespread [61]. The use of DSLs has a tradition in the Unix community where they are called “little languages” [145]. A discussion of popular DSLs available under Unix is given by Raymond [141]. There is a plethora of literature that describes the implementation and use of DSLs, an annotated Bibliography is pro- vided by Deursen et al. [163]. Much of the research on DSLs is concerned with how to build DSLs using specific technologies, e.g., specialised parsing techniques and frame- works [20, 133, 134], code generation [67] or the meta-programming facilities of specific languages [37, 47, 103, 160]. Less work exists on techniques for creating and relating DSLs. Methodologies for developing DSLs are proposed in [117] and [113]. The former includes a broad study of DSLs, the latter focuses on formal methods for creating DSLs. Concat and XMF are tools that can be used for creating domain specific programming, specification and modelling languages.

2.7 Concatenative Programming

The execution mechanism of Core Concat restricts rewriting in such a way that it con- forms to a concatenative programming language. Concatenative languages can be re- garded as a purely functional version of stack languages. The interesting aspect of con- catenative languages for this work is that these languages provide a simple computational foundation that – unlike lambda calculus – is not based on the concept of variables and their substitution. The simple structure and the non-existence of variables makes transfor- mations of concatenative programs particularly simple [70].

Much of the foundational work on concatenative languages was performed by Man- fred von Thun in conjunction with the development of the Joy programming language [169]. Cat [42] is a concatenative language that – unlike Joy – supports static type check- ing. Factor [45] is a programming language designed for use in practice. It has a concate- native core, but also supports object-oriented programming and a macro system.

Concatenative languages are closely related to stack languages. The former are char- acterised by the homomorphic relationship between programs and functions, the latter by the use of a stack as the central concept in the execution model. A language may be both stack-based and concatenative, but this must not necessarily be the case. Forth [140] and PostScript [2] are popular “high-level” stack-based languages that are not concatenative. Several assembly and intermediate languages also use a stack-based model of execution.

In a concatenative language, even those words that may intuitively be perceived as data, for example numbers and strings, denote functions. Thus, concatenative languages are not only functional in the sense that functions have no side effects, but also in the sense that “everything is a function”. This form of purity and the non-existence of variables relates them closely to function-level programming as defined by Backus [7] and the point-free style of functional programming [58].