The systematic usage of the models (components) across the .... Figure 1. Unified view at the transformation processes. We use this model in the following analysis. In this paper, we ..... parameters in the generic port map statement in. VHDL.
ISSN 1392 – 124X INFORMACINES TECHNOLOGIJOS IR VALDYMAS, 2002, Nr.1(22)
TAXONOMY OF THE PROGRAM TRANSFORMATION PROCESSES Vytautas Štuikys, Robertas Damaševicius Software Engineering Department, Kaunas University of Technology Studentu 50, LT-3031, Kaunas, Lithuania Abstract. We present an analysis and taxonomy of the program transformation processes, identify the transformation domains in software engineering, and consider an operational view to program transformations. The taxonomy is based on the analyzed transformation approaches in HW design, as well as HW/SW co-design systems. Finally, we present a case study: the transformation (packaging, wrapping and customization) of VHDL components with the program modification language Open PROMOL.
1. Introduction
At the construction time, we need to accept that the prescribed requirements remain constant for the planned life cycle of the program to be constructed. In practice, however, this happens rarely. The need to change requirements during the life cycle leads to a modification resulting in the creation of a new version of the program. Hence, the modification is a part of the process for creating and managing different versions of the same program.
In general engineering sense, the program transformation is a manipulation with its representation resulting in the change of the form (syntax) of the program. Its semantics may be changed or not in the process. A step-wise manipulation, which (1) is defined on a programming language domain, (2) uses a formal model to support the refinement, and (3) simultaneously preserves the semantics, is known in the literature as a formal program transformation. The general case, however, is the one, which does not require the usage of the formal model as well as has no restrictions on the changes of its semantics. In order words, the general case comprises all possible manipulations with a program, which further we consider as an abstract transformation or simply transformation.
The other important reason for a transformation of a program is its reusability. In a pure technological sense, the modification is a part of the reuse process consisting of finding, understanding, modifying and re-using in the new context the artifacts (documentation, program code, specification, etc.) previously developed and used by others. For well-understood domains, such as hardware design using a high-level language (VHDL, Verilog), there is a great amount of the ‘look-alike’ models described in the language. The need to have the same functionality with the slightly different characteristics for different applications, e.g., area, performance, energy consumption, or trade-offs of these characteristics can explain the diversity of the models.
Two extremes are with the transformation: a program can be transformed either at its construction phase or at the execution phase. We consider a specification developed at the construction phase as a pre-programmed transformation. The wide spectrum of the transformations ranges from the editing, modification, translation, and generation to the packaging, wrapping, and customization. We specify the reasons and context of the usage of transformations below. In the simplest form, the program transformation appears in the applications, which require improving the performance characteristics of the given program. The example is enrolling of the loops or substitution of common expressions in a program. More generally, for a well-understood domain, such as algorithms for implementing scientific calculations (Fourier Transform, etc.), this problem is known as a partial evaluation or program specialization [1].
The systematic usage of the models (components) across the different application domains requires that those related models would be represented in the form of a single generalized specification. The latter can be achieved through the systematic usage of a modification procedure in the construction phase of the model supported by the tools implementing an adequate abstraction. The generalization itself as a higher level transformation is important in many aspects. Perhaps, the most important one is that a generalized specification encapsulates a family of the related functionality, therefore, it is a methodological basis for developing the component-based generators for well-understood
39
V. Štuikys, R. Damaševicius
domains. This category of research is aiming to achieve higher productivity, thus attempting to close the so-called ‘productivity gap’ [2] in software and hardware design. In recent years, the researchers have paid a great attention to the issues (productivity, reliability, reusability, etc.) that are directly related to the program transformation. Due to the wide spectrum of the related publications and the common trend to raise the abstraction level in the design of a complex system, it is useful to analyze and evaluate the ever-increasing stream of publications.
Layer (2) deals with abstract processes, such as modification, adaptation, synthesis, which are expressed through the basic operations. The Transformation Layer (3) specifies a sequence of the processes to form the particular transformation in the given system. The Tool Layer (4) specifies the implementation or modeling of the domain content through the usage of the adequate abstractions and creating the environments to support transformations. The Methodology Layer (5) comprises models, languages and the variety of abstractions, which bridge the domain content with the tools and applications. Finally, the Application Domain Layer (6) is an abstract representation of the domain content.
The aim of the paper is (1) to suggest the appropriate framework for dealing with the program transformation systematically, and (2) to work out taxonomy of the transformation processes in order, as we hope, to receive better understanding of the area for improving the design processes.
Real world Application Domains Languages
The paper is organized as follows. We suggest a unified framework for the analysis of the transformations in Section 2. We deliver an overview of the program transformation systems in Section 3. We introduce the 2D view to the transformation systems in Section 4. In Section 5, we suggest taxonomy of the transformations along with the definitions of the most frequently used processes. In Section 6, we describe the operation view to the transformations. In Section 7, we introduce software transformation domains, which is a generalization of the proposed taxonomy. In Section 8, we deliver some experiments as a case study. In Section 9, we evaluate the results and present the discussion. Finally, we present conclusions in Section 10.
Methodologies
Models
Tools
SW Resources Construction phase SW Highlevel
Transformations
Techniques Methods HW Resources Execution phase
Processes Operations
HW Lowlevel
(1) (2) (3) (4) (5) (6)
Figure 1. Unified view at the transformation processes
We use this model in the following analysis. In this paper, we restrict ourselves in dealing with the program transformation processes and systems, leaving the analysis of abstractions and methodologies for further research.
2. Framework for analysis We suggest the multi-layered scheme (Figure 1) as a general framework for analyzing the program transformation processes and tools (systems). The framework is dedicated for both domains: the SW and HW ones. The explanation of such an approach is simple – from the methodological (e.g., abstractions used, component-based frameworks and reuse) viewpoint, nowadays these domains are as much related as they were at the dawn of computing. For example, the direct indication to this relationship as well as an implicit intention to it can be found in books [2, 3], and many other publications and speeches of the speakers at the conferences (e.g., DATE’01, FDL’01).
3. Overview of the program transformation taxonomies and systems First, we will review the transformation taxonomies presented in the known papers, and then we will analyze the HW design systems with respect to the transformation processes. 3.1. Transformation taxonomies
Our model (see Figure 1) brings two important issues as follows. Firstly, we distinguish the hierarchical inter-dependency between the six layers (Operations, Processes, Transformations, Tools, Methodologies, and Application Domains). Secondly, we emphasize the duality between SW and HW up to the Tool Layer. The Operation Layer (1) contains basic operations such as insert, delete, replace, etc., without specifying the context of the usage. The Process
Partsch [4] divides the transformation systems into three classes: the manual, semi-automatic, and fully automatic ones. (1) The manual transformation systems require the user to be responsible for every single transformation step. The user generally selects a transformation he (she) wants to apply to the system from a set of available transformations.
40
Taxonomy of the Program Transformation Processes
(2) The semi-automatic transformation systems intend to automate as much of the transformation process as possible, while still allowing the transformation of a large class of programs within the paradigm. (3) The fully automatic transformation systems intend to fully automate the programming process. Once a specification has been written and verified formally, it is possible to completely automate the transformation of this specification into a correct program, which is efficiently executable on a computer.
(1) Algorithm Derivation is for transforming a declarative specification into an operational procedure, which produces values satisfying the specification. Systems usually perform the algorithmic refinement by using algorithm schemas, i.e., the generic algorithm templates that allow the limited specialization for particular data representations and special purpose operations. (2) Data Type Refinement is a complementary refinement to the algorithm derivation and aims at selecting an implementation for data types in a specification. The optimizing transformations attempt to improve the performance of the produced program by transforming it into a more efficient program, at the same conceptual level of abstraction. Those transformations fall mainly into three categories: (1) Partial Evaluation is a general technique for specializing general pieces of code for use in the concrete contexts. The partial evaluation can be implemented through pattern-based transformations but the most complex cases are usually treated programmatically. Two special cases of partial evaluation are specialization (producing a new function by fixing some of the arguments of an existing one) and constant folding (performing computations on constants at compile time). (2) Incremental Optimizations are a group of techniques that perform complex computations incrementally. One such a technique is finite differencing (aka formal differentiation). The finite differencing substitutes expensive computations that occur in a specific pattern (e.g., in a loop) with an incremental update of the result of the previous computation in the pattern. (3) Code Restructuring transformations comprise several optimization techniques based on the control and data flow. These include traditional compiler optimizations like dead code elimination, loop unrolling, loop invariant code motion, as well as techniques like loop fusion. Some of these ideas were implemented in the GenVoca model [7]. The model is a component-based reuse strategy in which the components play the role of layers of abstraction in the program construction process. GenVoca components actually define sophisticated program transformations that convert the domain-specific language constructs into their target language implementations. In this way, a domainspecific program is reduced (transformed) into an executable target language program by a series of transformations, where each transformation corresponds to a component in a domain-specific transform library.
Partch describes the intentions of these transformation systems as follows: (1) Program modification, such as an optimization of the program’s control structure and efficient implementation. (2) Program synthesis, i.e. the generation of programs from the description of a formal specification of the problem. The specification may be in the restricted natural language or in some formal language. (3) Program adaptation, i.e. changing a program to some particular environments, such as the change of the system programming language. Winter [5] mentions two types of transformations, the procedural and schematic ones: (1) Procedural transformations (aka global rules or semantic rules) are algorithms, which operate on entire programs and produce other programs, e.g. the flow analysis. They apply to the context-dependant aspects of a programming language. (2) Schematic transformations are syntax-oriented transformations, which are used to make local changes to programs. These rules generally are more amenable to the human perception, but have the disadvantage of being poorly suited for expressing different kinds of the global information. Winter describes the goal of the transformation system as modification, optimization or synthesis: (1) Program modification involves making changes to data structures, other related program changes or even modifying the semantics of the program. (2) Program optimization improves the efficiency of a program while preserving its meaning (i.e., producing a more efficient program which has the equivalent semantics). (3) Program synthesis aims to obtain an executable program from a non-executable specification. Smaragdakis and Batory [6] classify transformations as refinements or optimizations. A refinement adds the implementation details to an abstract specification. For instance, an abstract data type, like a set, may be refined for implementing using a specific data structure, like a binary tree. Refinements can occur at many levels and may fundamentally affect the program structure and performance. Two common types of refinements are as follows:
Lakhotia [8] presented a software maintenance system DIME (Direct Manipulation Environment) that uses semi-automatic step-by-step program transformations for software evolution. The theoretical foundation of DIME consists of a catalogue of the
41
V. Štuikys, R. Damaševicius
evolutionary transformations – transformations performed by programmers during software evolution. This catalogue was compiled by analyzing the author’s journal containing his record of programming activities. The author uses the word transformation broadly as a “mathematical mapping”. While most of the transformations actually modify a program’s structure, others are used for program analysis. According to Lakhotia, the evolutionary transformations are as follows. The fold transformation creates a function for a given set of statements and replaces the statements by a call to this function. The unfold transformation replaces a function call by the statements in the body of the called function. The inline transformation unfolds a function at all the places from where it is called. The split transformation splits a single-entry, single-exit region (i.e., block of statements) into two regions, one containing all the computations relevant to a set of statements and the other containing all the remaining computations. The move transformation moves a statement over the statements before or after it in the control flow, but within the same function. The pushup transformation pushes a statement from a function to its call-sites. The pushdown transformation pushes a statement from the call-site into the body of a called function. The rename transformation changes the name of a program component, such as a function, a variable, a type, or a file. The reorder transformation changes the order of the parameters of a function. The rescope transformation changes the scope of a variable , for instance, it changes a global variable into a parameter. The group transformation collects a set of variables into a structure (record). The ungroup transformation decomposes a structure and creates a variable for each of its fields. The wedge transformation converts the procedural program into an object-based program. Evolutionary transformations of Lakhotia are similar to the restructuring transformations mentioned by other authors [6, 9]. Wu, Sander, and Jantch [10] distinguish two levels of transformations: (1) Transformation rules are primitive transformations, which include (a) definition, (b) unfolding, (c) folding, (d) abstraction, and (e) algebraic rules. They introduce new functions to the system model, replace a function call with its definition and vice versa, abstract common expressions used in system models into one separate function to be reused, and define algebraic rules, respectively. (2) Transformation patterns describe more complex transformations, which capture intelligent design techniques and, in many cases, can be the application and implementation related.
have an impact on non-functional properties such as performance and cost. The semantic preserving transformations can be freely applied without changing the functionality. (2) Decision transformations are decisions, which are taken during the refinement process from the high abstraction level down to the implementation, and also affect the functionality. In addition, authors group the transformations used for optimization as follows: (1) Skeleton-based transformations are usually employed on the architecture model and depend on the design library, which contains implementations for skeletons and library elements. (2) Local transformations are employed on the elementary functions inside the skeleton. They can be introduced by skeleton-based transformations, for example merging and splitting skeletons usually require some local transformations. (3) Data type transformations are usually employed to transform data structures. The examples are splitting a signal into several signals to be processed by several processes simultaneously to acquire a higher efficiency, and transforming data structures (e.g. trees and lists) to meet the specialized system implementation. Visser presents program transformation taxo nomy in [11]. The author distinguishes two types of the program transformation: (1) translation, where the source and target languages are different; and (2) rephrasing, where the source and target languages are the same. Translation transforms a program in a source language into a program in a target language, which is different than a source language. It aims at preserving the semantics of a program, though it is usually not possible to retain all information. Translation can be divided into synthesis, migration, reverse engineering, and analysis. Synthesis lowers the level of abstraction of a program. Refinement derives an implementation from a high-level specification such that the implementation satisfies the specification. Compilation is a form of synthesis in which a program in a high-level language is transformed to machine code. Migration transforms a program to another language at the same level of abstraction. Reverse Engineering extracts a high-level program, specification, or at least some higher level aspects from a low-level program. Particular cases of reverse engineering are as follows. Decompilation translates an object program into a highlevel program. Architecture extraction derives the design of a program from a program. Documentation generation produces informal description of a program from a program. Software visualization depicts some aspects of a program in an abstract way. Analysis reduces a program to one aspect, such as its control or data-flow.
Orthogonal to this, authors classify transformations in the following way: (1) Semantic preserving transformations do not change the functionality of the system, but they may
42
Taxonomy of the Program Transformation Processes
Rephrasing is another type of transformation that transforms a program into a different program in the same language, i.e. the source and target languages are the same. In general, rephrasing tries to improve some aspect of the program, i.e. it changes the semantics of the program. The main cases of rephrasing are as follows: normalization, optimization, re-factoring, obfuscation, and renovation. Normalization reduces a program to a program in a sub-language, with the purpose of decreasing its syntactic complexity. Optimization improves the runtime and/or space performance of a program. The examples of optimizations are fusion, inlining, constant propagation, constant folding, common sub-expression elimination, and dead code elimination. Re-factoring improves the design of a program by restructuring it in such a way that it becomes easier to understand while preserving its functionality. Obfuscation makes a program harder to understand by renaming variables, inserting dead code, etc. Obfuscation is done to hide the business rules embedded in software by making it harder to reverse engineer the program. Renovation changes the extensional behavior of a program in order to repair an error or to bring it up to date with respect to the changed requirements.
descriptions from the high-level functional specifications. The system is a formalization of a digital design based on a functional algebra. The specifications are written in SCHEME. The descriptions are built from the applicative terms, constants, identifiers, conditional expressions, and function definitions, and express globally synchronized systems. In DDD, there are three classes of transformations as follows: (1) Behavioral transformations manipulate the behavioral specification. These transformations usually involve manipulating the control and architecture. Some examples include folding and unfolding transformations to achieve a proper scheduling of operations. (2) Structural transformations manipulate the sequential system description, which was built from the behavior description. These transformations are intended to refine the structural specification to the architecture. (3) Projection transformation is a mechanism of incorporating representations of an abstract type by another a more concrete type. The projection allows the derivation of real hardware from the concrete behavioral specifications. The CAMAD (Computer-Aided Modelling, Analysis and Design) [14] high-level synthesis system takes an algorithmic (behavioral) specification of a digital system and a set of design constraints as input, and generates the register-transfer level (RTL) implementation. The input specification is given in Algorithmic Design Description Language (ADDL). CAMAD maps the ADDL specification into the Extended Time Petri Net representation, to which the correctness-preserving transformations are then applied successively until the final implementation is created. During these transformations, design tradeoffs are made to optimize either the cost or the performance under a set of design constraints. The set of transformations used can be divided into three groups based on their functions: (1) Operation Scheduling Oriented Transformations deal with (a) determining the serial/parallel nature of the design, (b) dividing or grouping operations into time steps, and (c) changing the order of operations. (2) Data Path Oriented Transformations include vertex merger transformation and the constant merger transformation. (3) Control Oriented Transformations include the control merger, and condition-signal grouping merger transformations.
3.2. HW design and HW/SW co-design systems The OLYMPUS Synthesis System [12] is a design tool for specification and synthesis of digital circuits. A hardware design language, HardwareC, is used for design specification. The input of the HardwareC description is parsed and translated first into an abstract syntax tree representation, which provides the underlying model for semantic analysis and behavioral transformations. The transformations are categorized into the user-driven and automatic ones. The userdriven transformations include (1) the selective inline expansion of model calls, and (2) the selective operator to library mapping. The automatic transformations include the following procedures: (1) For-loop unrolling unrolls the fixed-iteration loops to increase the scope of the optimizations. (2) Constant and variable propagation replaces the reference to a variable by its last assigned value. (3) Reference stack resolution resolves multiple and conditional assignments to variables by creating multiplexed values that can be referenced and assigned. (4) Common sub-expression elimination removes the redundant operations that produce the same results. (5) Dead-code elimination removes the operations whose effects are not visible outside the model. (6) Collapse conditional collapses the conditionals with branches containing only combinatorial logic in order to increase the scope in which logic synthesis can be applied. (7) Data flow analysis identifies the data and control dependencies among the operations.
TRADES (Transformational Design System) [15, 16] is a design methodology based on the designerdriven application of small, local, behavior-preserving design transformations, which include optimization transformation, refinement transformation, space-time transformation (deals with area/delay trade-offs), composite transformation, etc. It is the responsibility
DDD (Digital Design Derivation System) [13] is a transformation system that implements the basic design algebra for synthesizing digital circuit
43
V. Štuikys, R. Damaševicius
of the designer to select between these possibilities. The initial design specification is written in VHDL (or C, Silage), which is first translated into SIL design representations. The transformation engine then provides a user interface that allows the designer to select a series of transformations from the hierarchical list of transformations defined by a designer. After the transformation, a SIL to VHDL Translator generates the VHDL code, which can be synthesized using commercial RTL synthesis tools. Cheung [17, 18] presents a transformational codesign methodology. The refinement process is separated into two levels, the algorithmic and structural ones. Within each level, the refinement is accomplished by applying sequences of transformations that preserve the functionality of the initial specification. The transformational co-design process starts with a form specification of a task and constructs an algorithm that computes the desired function. The resulting implementation function is to be partitioned into hardware and software parts, which satisfy the cost constraints. The final structural forms are mapped into the target implementation technologies to produce the high level pseudo-code for the software components and applicative descriptions for the digital hardware components. A set of syntactic transformations defines a calculus (algebraic rules) for the form is used in the transformation process. The rules permit the symbolic manipulation of the form expressions during the structural transformation. The other transformation mechanisms are as follows: the recursion removal, conditional resources sharing, multiplexer reduction, parallelization, serialization and loop unfolding transformation ones. COSMOS [19] is a semi-automatic methodology for hardware and software co-design system. The approach is user-guided and assumes that the designer starts with an initial specification and an architectural solution in mind. The design of a system from the specification to implementation is performed through a set of primitives that perform basic transformations such as split, merge, move, flat and map. The initial specification is given in the system-level specification language SDL. The whole refinement process is based on an intermediate form called Solar. The output is a virtual prototype of the architecture given in a distributed C-VHDL model.
where the designer spends an additional effort to produce an efficient implementation. ForSyDe (Formal System Design) [10, 20] is a system, which models the method based on a formal functional model and on skeletons. Skeletons are higher-order functions whose inputs and outputs are signals. The objective of the system is to eventually develop both powerful formal analysis techniques and a full-fledged refinement and synthesis process. ForSyDe is extended by a systematic refinement methodology based on transformations, which gradually transforms a high-level, function oriented system description into a synthesizable model. Authors group transformations according to three different criteria as follows: (1) whether they preserve semantics or they constitute a design decision; (2) whether they are simple rewriting rules or complex patterns; (3) whether they transform combinatorial functions, skeletons or data types. We have overviewed only a small part of the SW and HW design systems and the transformation processes within those systems. We summarize the overview as follows: (1) To achieve the pre-specified aims, the analyzed tools implement an abstract and/or formal model. (2) The tools perform a variety of the transformation processes at the different level of abstraction. (3) At the lowest level processes are expressed by appropriate rules or sequences of operations. (4) Despite of a diversity of the systems and the characteristics of the transformations, we can analyze the transformation processes more generally either horizontally or vertically as detailed in the next section.
4. The 2D view to the transformation processes In this paper we apply the principle of the multidimensional separation of concerns [21] as a theoretical basis for our analysis. There are many overlapping aspects or concerns when dealing with transformation processes. Every concern relates to the different activity or domain of application. Related concerns can be grouped into kinds or dimensions, which emphasize a particular aspect of a problem. A model of a problem is obtained when dimensions are re-composed together. The analysis of the problem (transformation processes, in our case) is performed as follows. First, different aspects of a problem are decomposed into concerns. Then related concerns are grouped into dimensions. Finally, dimensions are integrated back to form a model.
The transformations are based on a powerful set of primitives for functional partitioning, structural reorganization and communication transformation. They allow the designer to transform the system, following an incremental refinement scheme, in a distributed model that matches with the architectural solutions. Each step reduces the gap between the specification and realization by fixing some implementation details, or by preparing future implementation steps. This methodology can be seen as a human guided compilation
Perhaps, most of the transformational processes can be analyzed through the paradigm of four essential changes over the model used within the system. Those changes are as follows: the functional, structural, logical, and physical ones. We distinguish vertical and
44
Taxonomy of the Program Transformation Processes
horizontal aspects of transformations. They are also treated as the abstraction and implementation ones (see Figure 2).
process; and (2) is performed using some higher-level abstractions usually aiming at concise expressing of different aspects, and widening a context of the usage. It enhances reusability and increases applicability. The generalization includes the development of specifications to support the execution of an abstract model, too. From the methodological viewpoint, sometimes it is useful to concentrate attention on the transformation issues either at a higher or lower level. In the first case, we distinguish the construction phase transformations as pre-programmed modifications. We distinguish two types of models of the transformations: the abstract and the formal ones. By the abstract ones we mean those which do not require the usage of the strict (formal) validation procedure (it is performed experimentally as a part of the software engineering process). On the contrary, the usage of the formal model requires to be supported by the formal verification methods. For the abstract model, we distinguish two kinds of transformations: the domain functionality-oriented and implementation technology-oriented ones. By the functionality-oriented ones we mean those, which are explicitly related to expressing domain functionality via widening, narrowing, isolating, and configuring domain functionality. By the technological processes we mean those, which are closely related to the implementation (e.g., customization, specialization, structuring, composition). A separate issue is the formal transformations, which are beyond our current research. The above stated issues imply the urgent need to give definitions of the processes analyzed. Below we present the definitions of the transformation processes, as we understand them (some of them are newly suggested, whereas others are accepted from the literature). An (abstract) transformation is any possible manipulation with a program. Modification is a process of transforming programs to meet new requirements. When applied to the black-box components it is referred to as adaptation. We think of modification as concerned with the construction phase, as well as with the execution phase of the program.
Vertical aspects deal with abstraction levels: (1) physical (low-level), and (2) logical (high-level). In case of program transformations, the first one deals with separate program statements (e.g., loop unrolling), whereas the second one deals with entire components (e.g., adaptation). Horizontal aspects of transformations deal with implementation details: (1) functional aspects deal with the behavior of programs, whereas (2) structural aspects deal with the internal structure of programs. Implementation aspects
Logical
Structural
Physical
Abstraction aspects
Functional
Figure 2. 2D view to the transformational processes
It is not obligatory that all four forms would occur in some concrete system. The simplest example of the logical transformation is the call to a function, while the loop merging, substitution of common expressions by a single one, etc. are examples of the physical transformations. The main intention of the introduced notation is to define the processes and analyze them systematically.
5. Taxonomy of the program transformation processes On the basis of the analyzed works, we can conclude two important issues. The first is that we need to deal with the transformation either at a higher level, the construction phase, or at a lower level, the execution phase. The second is that any transformation, either an abstract or a formal one, should be supported by a generalization using some abstraction at the construction phase of the component, and by the generation at the execution phase of the transformation process. Despite of the fact that there is a thin line between these two phases, the separation of concerns plays an important role in this context. We have accepted it as a basis for our taxonomy.
Generalization is a process of deriving a generic specification, which, e.g., may represent a family of ‘look-alike’ components, where variations of the components are represented at a higher level of abstraction. The reverse process of deriving specific component instances from a generic specification is specialization, i.e., narrowing of the application domain of the component. Specialization is usually achieved via customization. Customization is a process of modifying a software component by choosing a particular implementation of it (usually denoted by parameters) from a fixed set of options. Examples are template customization in C++, or specifying generic parameters in the generic port map statement in VHDL.
The proposed taxonomy (Figure 3) should be conceived as follows. The ‘fuel’ for any kind of transformations is a generalization, the most general process. The generalization (1) implements the multiaspect view (e.g., functional, architectural, etc.) to the
45
V. Štuikys, R. Damaševicius
Transformation at Generalization
Technologyoriented
at Modification
Construction Phase Processes based on Abstract Model for
Functionalityoriented
Execution Phase
Formal Model
Processes based on
Generation
Abstract Model
Customization
Widening
Specialization
Narrowing
Structuring
Isolating
Translation
Composition
Configuring
Rephrasing
Visser’s processes
Lakhotia’s processes
Other processes
Figure 3. Taxonomy of the transformation processes
Generation is a process of creating lower-level code from a higher-level specification. We distinguish (1) logical generation (aka instantiation), when the process is implicit (e.g., instantiation of VHDL generic components), and (2) physical generation, when the process is explicit and actual code of the instance is derived (e.g., generation of instances from PROMOL generic components). Composition is a process of putting separate pieces of the existing program code together. We distinguish two types of composition: (1) logical composition (aka wiring, plugging), when components are connected via their interfaces (ports), and (2) physical composition (aka gluing), when programs are composed from statements or parts of them. Particular cases of composition are wrapping and packaging.
The following definitions of the functionalityoriented transformations are given according to Sametinger [22]. Widening is extending of the requirements (functionality) of the component, so that a component is more likely to be reused in future applications. Narrowing is the limiting of the functionality of the component at the cost of larger number of components. Isolating is the separating of specific requirements (functionality) to certain components or parts of them. Usually parameters serve as a means of isolation. Configuring is the building a larger system from a set of smaller components, which can be composed in various ways in order to meet different requirements.
Wrapping is a process of adding a new functionality to the existing component. Packaging (aka encapsulation) is a process of hiding functionality of a component behind a higher-level interface. For example, putting methods into classes in C++, or procedures into packages in VHDL.
Note that the above-defined processes can be expressed through the adequate operations at the lowest layer (see Figure 1).
6. Operational view to the transformation processes
Structuring (aka restructuring, modularization) is a process of changing a program structure, (e.g., introducing a hierarchy of modules). The examples are building the structural description of a model from the behavioral one in VHDL, or function folding/unfolding in C++.
We assume that the final state of the program, which satisfies the initially prescribed requirements, is achieved via a sequence of modifications. Here we concentrate our attention on the syntactical manipulations as they can be seen through the usage of the modification language Open PROMOL, which we have developed to support a wide range of modifications [23, 24]. Application of Open PROMOL for the program specialization was considered in [25].
Optimization is a process of improving program performance. Optimization can be semantics-preserving (e.g., loop unrolling, constant propagation), as well as semantics-loosing (e.g. partial evaluation). Partial evaluation (aka program specialization) is a process of simplifying a program (usually a function) with respect to partially known inputs, thus hoping to increase runtime performance of the program.
The operations are at the core of the transformation processes. Perhaps, there are only a few categories of operations for syntactical manipulations. They are as follows: simple editing and syntax-directed
46
Taxonomy of the Program Transformation Processes
editing. A simple editing mainly focuses on manipulations with the plain text. A syntax-directed editing concentrates on the manipulation with the program as data, which are presented as a concatenation of terminals, non-terminals, and separators. The latter category, i.e., the syntax-directed editing, may require some preliminary calculations to be performed as it is stated in Table 1.
editing operation the result of the modification is concatenated with the initial specification. The suggested framework (see Figure 1) and the proposed concept (see Table 1) allow considering the transformations formally as well. We present the view to modification as a formal concatenation below. The operands for concatenation are the target language (TL) text and PROMOL functions.
As a result, we consider three categories of the editing operations: simple editing, syntax-directed editing without calculations, and syntax-directed editing with calculations. What is the main difference between these categories? We describe the differences from the perspective of capabilities for achieving generalization via modification. The differences follow: category 1 requires no parameterization, category 2 requires little parameterization support, and category 3 requires deep parameterization support. Finally, we use one common operation, i.e., concatenation, when we perform modifications. The usage of the operation follows in the natural way: each time after the execution of an
::= $ $ ::= ::= | | ::= concatenation ::= | | | ::= @sub | @if | @for | … | @macro
Table 1. Categories of the editing operations and context of their usage No.
Categories of the operations
Examples of the operations
Context of their usage
1
Simple editing, pre-processing
Insert Change
Plain text, manipulations with data files, text editing, Simple pre-processing
Delete Add 2
Syntax-directed editing within the target program fragments without calculations
3
Syntax-directed editing with calculations
Enrolling of loops Explicit representation of expressions Simple replication Calculation of expressions within target Generation of particular fragments Conditional editing
Manipulation with data and programs manually or automatically Manipulation with programs as data, usually automatically
Conditional replication
7. Software transformation domains
architecture that has the same functionality, but different non-functional properties (e.g., performance, reliability, fault-tolerance, etc.). For example, design pattern transformations. (3) Construction-time transformations are performed when implementing programs from architectures and vice versa. Examples of such transformations are program generation from architectures in program development systems (e.g., GUI generation), as well as architecture extraction in reverse engineering. (4) Paradigm-based transformations are performed over programming paradigms. For example, a transformation from procedural to object-oriented programs. (5) Language-based transformations are performed over programming languages. This type of transformations is also often referred to as program
As it has been shown, there are many processes in software engineering that could be considered transformational, for example, modification, adaptation, generalization, etc. Authors give many definitions, however, they are often too narrow, vague or even contradictory with each other. In this section, our objective is to present a wider view to the software transformation. We have identified the following software transformation domains (see Figure 4): (1) Design-time transformations derive architecture of a system from a high-level system specification or vice versa. Examples of such transformations are architecture generation from a high-level specification described in the architecture description language, or documentation generation. (2) Architectural transformations are changes to the architecture that lead to a new version of the
47
V. Štuikys, R. Damaševicius
transformations in the narrow sense of the word. The object of the program transformation is a program written in a specific programming language. Examples of such transformations are translation, prettyprinting, and optimization.
Figure 4) and reverse engineering transformations (marked by the upward arrows in Figure 4) is that in the first case the abstraction level is usually lowered, while in the second case the abstraction level is raised.
8. Case study: customization and wrapping of VHDL components with Open PROMOL
Requirements
As a case study, we explore customization and two particular types of composition: packaging and wrapping.
1
2
3 Abstractions Components
Languages
Paradigms
6
5
4
Software engineering
9
Reverse engineering
Architectures
Packaging and wrapping are close to each other, since both encapsulate existing code. However, packaging only adds a new higher-level interface, without changing the functionality and structure of the component, whereas wrapping actually adds a new functionality. We demonstrate both with respect to VHDL components using Open PROMOL as a means for coding necessary modifications. The processor EREBUS then processes PROMOL specifications and automatically derives the specific instances in VHDL.
9
7
8.1. Packaging
Executables
For example, we have an already developed PROMOL specification that generates multiplexers with the specified number of inputs. Multiplexers are implemented as VHDL procedures and generalized with Open PROMOL. The user may choose to generate either procedure declaration, or both procedure declaration and procedure body. The PROMOL interface of the mux_proc component is shown in Figure 5.
8
Figure 4. Software transformation domains
(6) Component-based transformations are performed over software components. Traditional component-based transformations are categorized into whitebox and black-box transformations. The white-box transformations (e.g., inheritance) generally require understanding of the internals of the transformed component, whereas the black-box ones (e.g., packaging) only require knowledge about the interface of the component. (7) Compile-time transformations are performed over the program source code during program compilation, e.g., parsing. (8) Executable code transformations are performed over executable programs, e.g. load-time Java byte-code transformation. (9) Universal transformations can be applied throughout the entire software development process to transform all domain objects (components, architectures, etc.). We identified two types of the universal transformations: (a) Structural transformations that change the structure of the transformed object (program, architecture, etc.). Examples of such transformations are: encapsulation, integration, composition, etc. (b) Functional transformations that change the functionality of the transformed object. According to Sametinger [23] these are widening, narrowing, configuring and isolating. The difference between the software engineering transformations (marked by the downward arrows in
$ "Enter the number of inputs:" {2, 4, 8, 16} num:=4; "What do you want to generate: 1 - procedure declaration 2 - procedure declaration and body" {1, 2} g:=2; $
Figure 5. Interface of the mux_proc specification
Our aim is to design a PROMOL specification, which generates a VHDL package containing the multiplexer procedures. A package is a collection of the source design units that contain frequently used declarations. It is a highly reusable structure allowing us to share data in different designs and isolate changes. The designer was presented with informal requirements for the multiplexer package as follows: the number of multiplexer inputs may be selected from the list {2, 4, 8, 16}. The package consists of two parts: a package header declaration and a package body declaration. The designer specified that generated procedure declarations should be glued into the package header declaration, and generated procedure bodies should be glued into the package body. Thus the packaging of
48
Taxonomy of the Program Transformation Processes
the multiplexer procedures is performed as shown in Figure 6.
IF (CLK'event and CLK = '1') THEN IF (RESET = '0') THEN Q 1, {_vector(@sub[width - 1] downto 0) }] }] @move[core,{ @sub[modsig] 1, {_vector(0 to @sub[width - 1]) }]; @if[en, { ENA : IN bit; }] @if[rs, { RESET : IN bit; }] @if[cl, { CLK : IN bit; }] Q : OUT bit@if[width > 1, {_vector(0 to @sub[width - 1]) }] ); END RegisterD _@sub[width]_@sub[en]_@sub[rs]_@sub[cl];
10. Conclusions 1) The more complex software components are the higher-level of abstractions we need to deal with them. The same is with the transformational processes, which describe the components.
ARCHITECTURE model OF RegisterD _@sub[width]_@sub[en]_@sub[rs]_@sub[cl] IS BEGIN PROCESS (D @if[en, {, ENA}] @if[rs , {, RESET}] @if[cl, {, CLK }] ) BEGIN @if[rs, { IF (RESET = '0') THEN Q 1, {" }, { '}] @rep[width, {0 }] @if[width >1 , {" } , { '}]; ELSE }] @if[cl, { IF (CLK = '1' AND CLK'EVENT) THEN }] @if[en, { IF (ENA = '1') THEN }] Q