a simple aspect-oriented language based on c#etd.dtu.dk/thesis/246031/bac09_17.pdf · summary this...

108
A simple aspect-oriented language based on C# Jakob Kragelund S062399 Kongens Lyngby 2009

Upload: vanhanh

Post on 15-Jul-2018

214 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: A simple aspect-oriented language based on C#etd.dtu.dk/thesis/246031/bac09_17.pdf · Summary This report, titled "A simple aspect-oriented language based on C#" is about my work

A simple aspect-oriented languagebased on C#

Jakob KragelundS062399

Kongens Lyngby 2009

Page 2: A simple aspect-oriented language based on C#etd.dtu.dk/thesis/246031/bac09_17.pdf · Summary This report, titled "A simple aspect-oriented language based on C#" is about my work

Technical University of DenmarkInformatics and Mathematical ModellingBuilding 321, DK-2800 Kongens Lyngby, DenmarkPhone +45 45253351, Fax +45 [email protected]

Page 3: A simple aspect-oriented language based on C#etd.dtu.dk/thesis/246031/bac09_17.pdf · Summary This report, titled "A simple aspect-oriented language based on C#" is about my work

Summary

This report, titled ”A simple aspect-oriented language based on C#” is about mywork on designing and implementing an aspect-oriented programming language.

Aspect-oriented programming is a programming paradigm that seeks to enhancethe modularity of programs, by facilitating the separation of cross-cutting con-cerns. Many common problems, such as logging, security and synchronisation,requires code that cuts across a series of other modules. Aspect-oriented pro-gramming allows the programmer to separate and encapsulate these function-alities, so tangling of the code can be avoided.

During this report, I will describe how I design and implement an aspect-orientedextension to the programming language C#, by developing a preprocessor con-taining a parser, which is able to generate a syntax tree based on the C# codegiven as input, and an aspect weaver, whose job it is to modify this syntax treewith the intent of weaving the different aspects of the program together.

The product of this project is a first version of an implementation of an aspect-oriented extension of the C# language, containing a series of basic functionalitythat illustrates the use of aspect-oriented programming in a modern program-ming language.

Page 4: A simple aspect-oriented language based on C#etd.dtu.dk/thesis/246031/bac09_17.pdf · Summary This report, titled "A simple aspect-oriented language based on C#" is about my work

ii

Page 5: A simple aspect-oriented language based on C#etd.dtu.dk/thesis/246031/bac09_17.pdf · Summary This report, titled "A simple aspect-oriented language based on C#" is about my work

Dansk Resume

Denne rapport med titlen ”Et simpelt aspekt-orienteret sprog baseret pa C#”handler om mit arbejde med at designe og implementere et aspekt-orienteretprogrammeringssprog.

Aspekt-orienteret programmering er et programmeringsparadigme som søger atforbedre programmers modularitet, ved at gøre det nemt at adskille funktion-alitet der gar pa tværs af moduler. Mange problemstillinger, sasom logning,kontrol og synkronisering, kræver at man skriver kode der gar pa tværs af enrække andre moduler. Aspekt-orienteret programmering tillader programmørenat separere og indkapsle disse funktionaliteter, sa man undgar sammenfletningaf koden.

I løbet af denne rapport vil jeg beskrive, hvorledes jeg designer og implementereren aspekt-orienteret udvidelse til programmeringssproget C#, ved at udarbejdeen præ-processor, indeholdende en parser der kan generere et syntakstræ pabaggrund af C# kode, og en aspect weaver, som star for at modificere dettesyntakstræ med henblik pa at væve de forskellige aspekter sammen.

Produktet af dette projekt er en første version af en implementering af en aspekt-orienteret udvidelse af sproget C#, som indeholder en række grundlæggendefunktionaliteter der illustrerer anvendelsen af aspekt-orienteret programmeringi et moderne programmeringssprog.

Page 6: A simple aspect-oriented language based on C#etd.dtu.dk/thesis/246031/bac09_17.pdf · Summary This report, titled "A simple aspect-oriented language based on C#" is about my work

iv

Page 7: A simple aspect-oriented language based on C#etd.dtu.dk/thesis/246031/bac09_17.pdf · Summary This report, titled "A simple aspect-oriented language based on C#" is about my work

List of Figures

1.1 Class diagram for the running example without aspects . . . . . 6

3.1 Separation of concerns . . . . . . . . . . . . . . . . . . . . . . . . 15

4.1 Small example of a DFA . . . . . . . . . . . . . . . . . . . . . . . 20

4.2 Interactions between lexer and parser . . . . . . . . . . . . . . . . 22

4.3 Small parse tree representing a simple derivation . . . . . . . . . 27

5.1 Overview of the weaving process . . . . . . . . . . . . . . . . . . 41

5.2 The weaving process in more detail . . . . . . . . . . . . . . . . . 42

5.3 Class diagram for the aspect weaver . . . . . . . . . . . . . . . . 43

6.1 Big method parse tree . . . . . . . . . . . . . . . . . . . . . . . . 50

6.2 Small method parse tree . . . . . . . . . . . . . . . . . . . . . . . 51

6.3 The process of weaving before- and after-advice . . . . . . . . . . 56

Page 8: A simple aspect-oriented language based on C#etd.dtu.dk/thesis/246031/bac09_17.pdf · Summary This report, titled "A simple aspect-oriented language based on C#" is about my work

vi LIST OF FIGURES

6.4 The process of weaving around-advice . . . . . . . . . . . . . . . 61

Page 9: A simple aspect-oriented language based on C#etd.dtu.dk/thesis/246031/bac09_17.pdf · Summary This report, titled "A simple aspect-oriented language based on C#" is about my work

LIST OF FIGURES vii

Page 10: A simple aspect-oriented language based on C#etd.dtu.dk/thesis/246031/bac09_17.pdf · Summary This report, titled "A simple aspect-oriented language based on C#" is about my work

viii Contents

Page 11: A simple aspect-oriented language based on C#etd.dtu.dk/thesis/246031/bac09_17.pdf · Summary This report, titled "A simple aspect-oriented language based on C#" is about my work

Contents

List of Figures iii

1 Introduction 11.1 General introduction . . . . . . . . . . . . . . . . . . . . . . . . . 21.2 Topics of this project . . . . . . . . . . . . . . . . . . . . . . . . . 31.3 Running example . . . . . . . . . . . . . . . . . . . . . . . . . . . 5

2 Problem statement 72.1 Feature specification . . . . . . . . . . . . . . . . . . . . . . . . . 72.2 Delimitation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8

3 Background 133.1 Aspect-oriented programming . . . . . . . . . . . . . . . . . . . . 133.2 AspectJ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 163.3 Advantages and disadvantages of AOP . . . . . . . . . . . . . . . 16

4 Theory 174.1 Grammars . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 184.2 Finite automata . . . . . . . . . . . . . . . . . . . . . . . . . . . 194.3 Lexical analysis . . . . . . . . . . . . . . . . . . . . . . . . . . . . 214.4 Syntax analysis . . . . . . . . . . . . . . . . . . . . . . . . . . . . 234.5 Parse trees . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 264.6 Auto-generated lexers and parsers . . . . . . . . . . . . . . . . . 28

5 Analysis & Design 295.1 AOP concepts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 295.2 Design . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 385.3 Chapter Summary . . . . . . . . . . . . . . . . . . . . . . . . . . 44

Page 12: A simple aspect-oriented language based on C#etd.dtu.dk/thesis/246031/bac09_17.pdf · Summary This report, titled "A simple aspect-oriented language based on C#" is about my work

x CONTENTS

6 Implementation 476.1 Tools and datastructures . . . . . . . . . . . . . . . . . . . . . . . 476.2 Weaving implementation . . . . . . . . . . . . . . . . . . . . . . . 526.3 Chapter Summary . . . . . . . . . . . . . . . . . . . . . . . . . . 65

7 Test 677.1 Ad hoc testing . . . . . . . . . . . . . . . . . . . . . . . . . . . . 687.2 Automated testing . . . . . . . . . . . . . . . . . . . . . . . . . . 697.3 Known issues . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70

8 Future work 738.1 Implement the rest of the C# 3.0 specification . . . . . . . . . . 738.2 More aspect-oriented functionalities . . . . . . . . . . . . . . . . 748.3 Implement a compiler back-end . . . . . . . . . . . . . . . . . . . 778.4 Use a different weaving strategy . . . . . . . . . . . . . . . . . . . 77

9 Conclusion 79

A Language guide 81

B Source code of running example 85

C Test cases 89

Page 13: A simple aspect-oriented language based on C#etd.dtu.dk/thesis/246031/bac09_17.pdf · Summary This report, titled "A simple aspect-oriented language based on C#" is about my work

Chapter 1

Introduction

In this thesis, I implement a simple, aspect-oriented programming language.Aspect-oriented programming is a programming paradigm, where the main fo-cus is on enabling the programmer to separate cross-cutting concerns, therebymaking programs more modular and easier to develop and maintain. Withaspect-oriented programming, the programmer does not need to worry so muchabout the tedious details, such as implementing security and logging in his mod-ules, and instead focus on the core concerns of his program, thereby makingprogramming more fun.

I create a language based on C# with added aspect-oriented features, by creatinga so-called aspect weaver that allows a programmer to write aspect-oriented C#programs and compile and execute them on the .NET platform.

This chapter serves as a general introduction to the project, by informally ex-plaining what aspect-oriented programming (AOP) is about, and what the aimof this project is in relation to AOP. It gives an overview of the different topicsthat this project covers, by listing the different areas of computer science thatare used, and by giving a general idea of what is accomplished by this project.Finally, it introduces a running example, which will be used to illustrate impor-tant concepts, and shows how the solution developed can be used in a simple,toy-like problem, with the hope that it will be clear how the solution can bescaled up to real-world usage.

Page 14: A simple aspect-oriented language based on C#etd.dtu.dk/thesis/246031/bac09_17.pdf · Summary This report, titled "A simple aspect-oriented language based on C#" is about my work

2 Introduction

1.1 General introduction

Aspect-oriented programming is a programming paradigm, designed to enhancemodularity further than what is allowed by object-oriented programming, byhelping the programmer to separate cross-cutting concerns.

When designing software using object-oriented methodologies, emphasis is usu-ally placed on separating the primary concerns of the program, such as datamanagement, business processes, presentation etc. as much as possible. This isdone through modularity, encapsulation and layered designs, where the presen-tation layer is separated from the logic layer, which in turn is separated fromthe data layer. The reasons for this separation of concerns are many, but mostimportantly, it is done to simplify program structure, to enable reuse of code,and to ease maintenance.

Some functionality or concerns, however, are more difficult to separate intoloosely-coupled modules. These concerns are usually secondary concerns suchas logging, security/authentication systems, synchronization and memory allo-cation. The very nature of these concerns means they overlap most, if not all,of the other modules, making them so-called ”cross-cutting concerns”. For ex-ample, to log which methods are executed, one must add logging code to all themethods one wants to log. If one wants to change the way this logging is done,one might have to change the code in all these methods.

Aspect-oriented programming seeks to address this, by helping the program-mer encapsulate these cross-cutting concerns in modules that are more easyto maintain. This is done by encapsulating the cross-cutting functionality inso-called ”Aspects”. Here, the programmer can write ”advice”-methods, whichadd additional behaviour to various points in other modules. This is the ap-proach of probably the most popular AOP implementation, AspectJ, and it isthe approach that this project will explore.

The purpose of this project is to explore how aspect-oriented programming isimplemented, by extending an existing language (C#) with new AOP features,inspired by AspectJ. We will see how one can create a program that extendsthe front-end functionalities of the C# compiler, such that the language sup-ports the aspect-oriented methodology as a complementary to the traditionalobject-oriented approach. Furthermore, to illustrate the uses of aspect-orientedprogramming, I develop a running example in the form of a piece of softwarethat will be programmed using the tool I develop in this project. The purpose ofthis running example is to show that aspect-oriented programming indeed canbe used to make programming simpler and more fun, by letting the programmeruse less time on writing and maintaining ”the plumbing” of the program, and

Page 15: A simple aspect-oriented language based on C#etd.dtu.dk/thesis/246031/bac09_17.pdf · Summary This report, titled "A simple aspect-oriented language based on C#" is about my work

1.2 Topics of this project 3

more time on the interesting parts.

1.2 Topics of this project

This section gives a quick overview of the topics that this project covers, toinform the reader of what he can expect from the following chapters. The scopeof the project, and how the different topics within computer science will beapplied, will be defined more formally in the following chapter. This is onlymeant to serve as a quick overview.

1.2.1 Aspect-oriented programming

Aspect-oriented programming, is the main topic of this project. I will cover AOPin general, and more specifically various relevant AOP concepts and processesthat will be of importance to the implementation.

Relevant AOP conceps and processes that I will examine are:

• Join points - points in the control flow of the program

• Pointcuts - a predicate that describes a set of join points

• Advice - method-like constructs that are executed at join points specifiedby pointcuts

• Aspects - class-like constructs that encapsulate advice and pointcuts

• Weaving - the process of making sure that advice is executed at the correctjoin points

These concepts will be discussed in Chapter 5, Analysis & Design, while Chapter6, Implementation, will describe how they are implemented.

1.2.2 Compiler theory

Theory about the workings of compilers are central to this project. A compileris a program that translates the source code for a program written in a pro-gramming language understood by the programmer, into a program that the

Page 16: A simple aspect-oriented language based on C#etd.dtu.dk/thesis/246031/bac09_17.pdf · Summary This report, titled "A simple aspect-oriented language based on C#" is about my work

4 Introduction

computer can understand and execute. Compilers are usually split into manycomponents, which can be grouped into two main categories: the front-end, andthe back-end. The front-end consists of lexical analysis, preprocessing as wellas syntax and semantic analysis. The front-end usually creates an intermediaterepresentation of the program, for example in the form of a parse tree, in addi-tion to maintaining a symbol table. The back-end then takes the intermediaterepresentation, optimizes it and finally generates code in the target language,usually some sort of byte code or assembly language, which can be interpretedor translated further into machine code.

Knowledge of how the front-end of a compiler works will be necessary, since thisproject is about enhancing C# with new functionalities. To do this, I will writea preprocessor, that executes before the regular C# compiler. This preprocessorwill do much of the same work that a normal compiler front-end does, such aslexical and syntax analysis, which will be covered in the following chapters.

Lexers/Parsers and intermediate representations

The two main components of the front-end are the lexer (also known as a scan-ner) and the parser, which handle the lexical and syntactical analysis. Lexicalanalysis is the process of taking a stream of characters from the input sourcefiles, and transform them into a stream of meaningful tokens such as languagekeywords, identifiers and so on. A lexer uses a finite automaton to transformgroups of characters into tokens, and passes them on to the parser.

The parser, which handles syntax analysis, receives the tokens from the lexer,determines if the grammatical structure of the stream of tokens is well-formedcompared to a specified formal grammar, and then generates a parse tree.

This parse tree is an example for an intermediate representation. It is meantto serve as a way to represent the original program in a form that is easy toanalyze and manipulate. A parse tree is a tree where each internal node isa non-terminal, and each leaf is a terminal symbol, as specified in the formalgrammar of the language.

Since I will use lexers and especially parsers, when I create the intermediaterepresentation of the program that the aspect weaver will be working on, I willdiscuss the theory behind these, such as automata theory, regular expressions,parsing and tree generation, in Chapter 4.

Page 17: A simple aspect-oriented language based on C#etd.dtu.dk/thesis/246031/bac09_17.pdf · Summary This report, titled "A simple aspect-oriented language based on C#" is about my work

1.3 Running example 5

1.3 Running example

To illustrate the points I am going to make in the following chapters, I willbe using a running example in the form of a small program. I will use aspect-oriented programming and my implementation of an aspect weaver to solve asmall problem, consisting of a very simple file system and user database, whereeach file has some restrictions on reading and writing, and each user has somepermissions.

The scenario of the example is a program designed to manage a list of files. Eachfile consists of some data, as well as some meta-information about the accesslevel required to read from and write to the file. The program also maintains alist of users, each described by a name and a list of access level flags.

The program should be able to create files with some initial data and accesslevel requirements, as well as users. Users should be able to read the data ofa given file, or append new data to a file, given that they possess the requiredaccess level. Finally, there should be some sort of logging, so that a systemadministrator can see who has accessed which files.

One can immediately identify 5 separate concerns in this program:

1. File functionality (read/write access to files)

2. User functionality (storing and managing users)

3. Handling the flow of the program, I/O, etc.

4. File security (checking read/write access requirements)

5. Logging reads and writes

The three first concerns can be encapsulated by use of a normal object-orientedprogramming concept: classes. A small class diagram is shown in figure 1.1that illustrates this. There is a File class, which encapsulates the file data andaccess level requirements, and provides methods to read from and write to thefile. There is a User class, which provides encapsulation for user data such asname and access levels. And finally there is a Program class which contains theentry point to the program and is responsible for managing files and users, etc.

Using only standard object-oriented programming, there are two ways to handlethe last two concerns. The first approach is to write code handling these concernsin the required places. For example, logging statements can be written directly

Page 18: A simple aspect-oriented language based on C#etd.dtu.dk/thesis/246031/bac09_17.pdf · Summary This report, titled "A simple aspect-oriented language based on C#" is about my work

6 Introduction

File

- FileData: string- ReadAccess: int- WriteAccess: int

+ WriteToFile(data: string, user: User)+ ReadFromFile(user: User)+ File(initial: string, readacl: int, writeacl: int)

User

+ UserName: string+ UserAccessLevel: int

+ User(name: string, acl: int)+ ToString()

Program

+ Main(args: string[])

* *

Figure 1.1: Class diagram for the running example without aspects

in each method, and the read- and write-methods in the File class can eachimplement the necessary security concerns. This, however, leads to scatteringof code, where the same piece of code is repeated in different places.

Another approach is to write logging and security classes, which provide thefunctionalities required, and then just invoke those classes whenever the con-cern they cover is needed. The problem with this approach is, that it leads totangling of the code, where one concern is required before another concern canbe implemented.

Scattering and tangling might lead to problems when interfaces or code ischanged, and might require one to update the same piece of code in severalplaces to change the functionality of a class. Aspect-oriented programming isa way to reduce these problems. With AOP, the security and logging concernsmight be encapsulated in two different aspects, and then the aspect weavermakes sure that the proper code is executed at the right places. This way, thedifferent concerns can be separated, for example by letting the File class worryabout implementing an interface for accessing files, and then implementing asecurity module that will worry about all the security aspects.

In the following chapters, I will return to this running example to illustratehow I can use different concepts from this project to implement the programdescribed above. The source code for the program can be seen in Appendix B.

Page 19: A simple aspect-oriented language based on C#etd.dtu.dk/thesis/246031/bac09_17.pdf · Summary This report, titled "A simple aspect-oriented language based on C#" is about my work

Chapter 2

Problem statement

In this chapter, I define the purpose and scope of this project. We look at theareas this project covers, and discuss which features will be implemented in theprogram.

2.1 Feature specification

The purpose of this project is to explore how aspect-oriented programmingmethodologies can be implemented, by writing a tool that extends the func-tionality of an established programming language, C#, with aspect-orientedfunctionalities. This project seeks to

Create a tool that extends the front-end capabilities of theC# compiler, which enables the programmer to use the aspect-oriented paradigm while writing a program in C#.

Page 20: A simple aspect-oriented language based on C#etd.dtu.dk/thesis/246031/bac09_17.pdf · Summary This report, titled "A simple aspect-oriented language based on C#" is about my work

8 Problem statement

The goal of this project is to create a tool that enables a programmer to writea, or take an existing, C# program, write some special ’aspect’-code and thenuse that code to add functionality to the original C# code. Or more precisely,to create a tool (an aspect weaver) that parses a C# program and some aspect-code, and then weaves the two together, generating a modified C# program,which can then be passed to a C# compiler of the programmer’s choice.

The following list specifies the elements that need to be designed and imple-mented in order to build this aspect weaver, and what functionality is desired.

1. A lexical analyser, or lexer. The purpose of the lexer is to read the streamof characters making up the source program and group them into tokens.(Aho et al., 2006, chap 1)

2. A syntax analyser, or parser. The parser’s job is to take the tokens gen-erated by the lexer, and create an intermediate representation of the pro-gram, in the form of a parse tree (Aho et al., 2006, chap 1). Two parsetrees will be generated, one for the aspect code and one for the C# code.

3. A weaver, which weaves the aspect code into the source program by mod-ifying the two parse trees.

4. A code generator, which outputs the two parse trees as C# code, to bepassed to a normal C# compiler.

2.2 Delimitation

As I have just stated, my goal is to create an aspect weaver, which enables the useof aspect-oriented methodologies. Unfortunately, aspect-oriented programmingis a broad paradigm, and incorporates many different concepts, which meansthat it has been necessary to delimit the set of goals that this project will seekto accomplish. This section describes some of the concious choices I have madein order to reduce the scope of the project. The purpose of this delimitation isfor me to be able to focus on a subset of the overall problem, which will enableme to create a better product. By doing this delimitation, I make it clear thatthe project can be extended with the features discussed below, as well as otherfunctionalities, by myself or others with an interest and time to work on this.

Most of the following sections discusses concepts that have not yet been in-troduced. If the reader has no knowledge of aspect-oriented programming, it isrecommended that the following sections be revisited after the relevant conceptshave been defined in Chapter 5.

Page 21: A simple aspect-oriented language based on C#etd.dtu.dk/thesis/246031/bac09_17.pdf · Summary This report, titled "A simple aspect-oriented language based on C#" is about my work

2.2 Delimitation 9

2.2.1 Reduced set of join points

AOP has a concept called a join point, which describes well-defined points in theexecution flow of a program. This can, for example, be execution of a method,a call to a method, the throwing of an exception, instantiation of an object, etc.(Jacobsen and Ng, 2005)

I have decided to limit the set of join points to execution of methods. Thismeans, that from the weaver’s point of view, a method is an atomic action, soadvice can only be injected before or after a method executes its body. Also,since object instantiations are not join points, one can not inject advice beforeor after a constructor.

The reason for this delimitation is to simplify the pointcut model. A pointcutis a predicate that covers a set of join points. A pointcut must therefore beable to determine if a particular join point matches the predicate, described bythe pointcut. The larger the set of join points, the more advanced pointcutpredicates are needed to be able to describe and distinguish the join points.

2.2.2 No dynamic pointcuts

When talking about pointcuts, one distinguishes between static and dynamicpointcuts. Static pointcuts are evaluated at compile-time, where the code isanalyzed to see which join points match which pointcuts. Thus, static point-cuts can not rely on run-time values of arguments or attributes, and pointcutpredicates can only consist of join point identifiers such as method names. Thismeans that pointcut evaluation need only be done once, during the weavingprocess.

Dynamic pointcuts, however, are not evaluated at compile-time, but at run-time. They may look at the state of the program to decide if a joinpoint ismatched by a pointcut.

To simplify the pointcut model, I have not included dynamic pointcuts in thisproject, since they are more advanced than static pointcuts. However, in Chap-ter 8, I include a description on how they might be implemented. In manycases, static pointcuts are sufficient because the advice method has access toboth dynamic and static information about the join point, such as the valuesof the arguments passed to the join point. Therefore, it is possible to manuallydecide if an advice should be executed at run time, by considering the informa-tion available from the join point, and simply returning from the advice method

Page 22: A simple aspect-oriented language based on C#etd.dtu.dk/thesis/246031/bac09_17.pdf · Summary This report, titled "A simple aspect-oriented language based on C#" is about my work

10 Problem statement

before the real advice has been applied, if some condition is not satisfied.

2.2.3 Subset of C#

As described above, the aspect weaver needs a lexer and a parser, to be able togenerate a parse tree from the C# code. This requires a description of the C#language in the form of a formal grammar. To reduce the time spent on thispart of the tool, only a subset of C# features are supported. My work is basedon the C# 3.0 specification, but the following features have been removed fromthe grammar:

1. Lambda expressions

2. Interfaces

3. Enumerations

4. Events

5. Operator overloading

6. Unsafe mode

7. Global attributes

8. Exceptions

Other (minor) things from the official C# 3.0 specification not on this list mightalso be missing from the grammar.

The reason for this delimitation is that many of these features are not neededto demonstrate the aspect-oriented features that are the scope of this project,and therefore they have been removed to allow me to focus on implementingthe AOP functionalities.

2.2.4 No inter-type declarations

A feature that would be interesting to implement is inter-type declarations (Pal,2003).

With inter-type declarations, it is possible to declare new members like fields,methods and constructors, that are owned by other types. This way, it is possible

Page 23: A simple aspect-oriented language based on C#etd.dtu.dk/thesis/246031/bac09_17.pdf · Summary This report, titled "A simple aspect-oriented language based on C#" is about my work

2.2 Delimitation 11

to add new functionality to a class, without modifying the existing code. Thiscan, for example, be used to implement the Observer pattern (Gamma et al.,1994), by using an aspect to add a list of observers to a class, as well as methodsto add, remove and notify observers. A pointcut can then be used to identifythe joinpoints where observers should be notified, and an advice method can beused to notify all the observers. This way, it is possible to separate the concernof having for example a GUI observe a data model, from the data model itself.

I have chosen not to implement inter-type declarations. Due to a lack of time, Ihave prioritized them lower than the features that I did have time to implement.However a description of how they could be implemented is given in Chapter 8.

Page 24: A simple aspect-oriented language based on C#etd.dtu.dk/thesis/246031/bac09_17.pdf · Summary This report, titled "A simple aspect-oriented language based on C#" is about my work

12 Problem statement

Page 25: A simple aspect-oriented language based on C#etd.dtu.dk/thesis/246031/bac09_17.pdf · Summary This report, titled "A simple aspect-oriented language based on C#" is about my work

Chapter 3

Background

This chapter discusses the background behind aspect-oriented programming,with the intent of clarifying why AOP is a research area that deserves some at-tention. I start by discussing the motivations behind aspect-oriented program-ming, by giving a small example that shows that AOP can be used to separatedifferent concerns in the source code of a program. Next, I discuss AspectJ,which is one of the most developed AOP implementations. AspectJ will serveas a big source of inspiration for this project, especially during the design-phase,where I will decide how I am going to implement AOP. Finally, I will sum upthe advantages and disadvantages of using aspect-oriented programming.

3.1 Aspect-oriented programming

Aspect-oriented programming has emerged from a long history of research intonew ways of separating concerns in program code into small, easier to maintain,reusable blocks of code. The general trend in the evolution of programmingparadigms has been to put higher focus on modularity. With assembly lan-guages, one could create subroutines to enable code re-use. This notion wasimproved upon with the procedural languages, where formal procedures wereintroduced to help programmers encapsulate their code. With object-oriented

Page 26: A simple aspect-oriented language based on C#etd.dtu.dk/thesis/246031/bac09_17.pdf · Summary This report, titled "A simple aspect-oriented language based on C#" is about my work

14 Background

programming, modularity and encapsulation were some of the biggest sellingpoints, and today, object-oriented programming languages such as C++, C#and Java are among the most popular languages in the software industry, ac-cording to TIOBE (2009).

Aspect-oriented programming seeks to take this trend of modulization and en-capsulation further, by solving some of the problems most object-oriented pro-gramming languages experience regarding separation of concerns. A commonissue that many programmers will recognize is when one has a cross-cuttingconcern such as logging, synchronization or transaction management, one hasto have copies of the same code again and again, since encapsulating theseconcerns in a module is hard and sometimes impossible. Take for example atransaction manager for a database that makes sure that only one process cando a transaction at a time, such that two processes trying to do a transactionwon’t interleave. To do this, one must gain a lock from the transaction man-ager, prepare and execute the transaction, and then release the lock when oneis done. Example 3.1 shows how this might look.

Example 3.1...tm = new TransactionManager();tm.obtainLock();/* Commit some transactionsQuery for new dataCommit some more transactions*/tm.release();..

Now imagine if there are many places in the code where this is needed — thecode that gets an instance of the transactionmanager, obtains a lock and releasesit again needs to be copied to all these places, and if the method of doing thisis changed in the future, the code in all of these places will need to be replaced.Figure 3.1 shows an illustration of this. In the upper half of the figure arethree different procedures, each needing some code to obtain a lock from sometransaction manager so that they may commit multiple transactions as oneatomic action. They also include some logging, so that the control flow of theprogram may be traced. We see that each procedure needs the same pieceof code. The lower half of figure 3.1 shows the same three procedures, butnow the cross-cutting concerns of obtaining and releasing locks and logging, areseparated into an advice method. The three procedures now only contain code

Page 27: A simple aspect-oriented language based on C#etd.dtu.dk/thesis/246031/bac09_17.pdf · Summary This report, titled "A simple aspect-oriented language based on C#" is about my work

3.1 Aspect-oriented programming 15

relevant to the purpose of the procedure, while other concerns are moved andencapsulated in an aspect.

This example shows the benefits and disadvantages of AOP: the transactionand logging concerns are separated from the rest of the code, which means thatchanges to either of these concerns only need to be done in one place. However,when one looks at one of the procedures, one can not see exactly what codeis executed. This is a big issue, since it makes it harder to get an overview ofthe code, but it can be solved by good development environments designed forAOP.

procedure A

Log(“Executing method A”)tm = new TransactionManager()tm.ObtainLock()

tm.submit( … )tm.query( … )tm.submit( … )

tm.ReleaseLock()Log(“Done with method A”)

procedure B

Log(“Executing method B”)tm = new TransactionManager()tm.ObtainLock()

tm.query( … )Calculate resulttm.submit( … )

tm.ReleaseLock()Log(“Done with method B”)

procedure C

Log(“Executing method C”)tm = new TransactionManager()tm.ObtainLock()

tm.submit( … )tm.query( … )tm.submit( … )

tm.ReleaseLock()Log(“Done with method C”)

Normal code without separation of concerns

procedure A:

tm.submit( … )tm.query( … )tm.submit( … )

procedure B:

tm.query( … )Calculate resulttm.submit( … )

procedure C:

tm.submit( … )tm.query( … )tm.submit( … )

Advice

around(“A” || “B” || “C”): Log(“Executing method “ + joinpoint.getName());tm = new TransactionManager()tm.ObtainLock()

joinpoint.proceed();

tm.ReleaseLock()Log(“Done with method “ + joinpoint.getName());

Aspect-oriented code with separation of concerns

Figure 3.1: Separation of concerns

Another problem, is when a cross-cutting concern is deeply tied to the concernsthat it crosses. This makes re-use of code harder, and is detrimental to theobject-oriented philosophy, since different concerns or functionalities are mixedtogether in the same place.

These two problems are commonly known as scattering and tangling, respec-tively, and aspect-oriented programming seeks to solve these two issues (Clarkeand Baniassad, 2005; Rosenhainer, 2004).

Page 28: A simple aspect-oriented language based on C#etd.dtu.dk/thesis/246031/bac09_17.pdf · Summary This report, titled "A simple aspect-oriented language based on C#" is about my work

16 Background

3.2 AspectJ

Aspect-oriented programming is not a new paradigm, and a lot of languageshave built in AOP support, or external libraries or extensions that enable AOP.AspectJ from Xerox PARC is an important and one of the most advanced AOPextensions to a language to date, and it is the source of inspiration for manyother projects, that aim to make different languages aspect-oriented. AspectJis ”a seamless aspect-oriented extension to the Java programming language”(AspectJ, 2009), and is a popular AOP implementation with a big set of features,as well as good IDE integration in the form of an Eclipse plugin (see AJD, 2009).

AspectJ is an open-source project that implements AOP as an extension tothe Java programming language. AspectJ uses bytecode weaving and a customJava compiler to create an extension to the Java language, which introducesnew language constructs such as aspects and advice.

3.3 Advantages and disadvantages of AOP

On the previous pages, I have discussed the motivation behind aspect-orientedprogramming. To sum up, the advantages of using AOP is

• Eases separation of concerns, by giving the programmer another means ofencapsulating functionality

• Reduces tangling and scattering of code, because crosscutting concerns areencapsulated in a module - the aspect weaver reintroduces the tangling andscattering when weaving, but this is invisible to the programmer

The disadvantages and pitfalls, that must also be taken into account, are

• It becomes harder to see exactly what code is executed. This can, to someextent, be made easier by good development tools

• Debuggers might become useless, if the AOP is not implemented correctly

Page 29: A simple aspect-oriented language based on C#etd.dtu.dk/thesis/246031/bac09_17.pdf · Summary This report, titled "A simple aspect-oriented language based on C#" is about my work

Chapter 4

Theory

This chapter serves as the primary source for the theoretical background of theanalysis, design and implementation of this project. Chapter 2 gave a list ofelements in the aspect weaver, and in this chapter, I present the theory necessaryfor some of these elements. As mentioned earlier, aspect weaving is related tocompiling, and uses some of the same components as compilers, such as lexicalanalysis, syntax analysis and generation of an intermediate representation. Thefollowing sections focus on these topics, where I cover the basic theory, discusshow the different areas relate to this project and how they are going to beapplied later when designing and implementing the aspect weaver.

It is not the goal of this project to write a lexer and a parser from scratch,so I will use an automated tool to generate these, but it is good to have somebasic knowledge of how the lexer and the parser works. Knowing that thetools used are built on sound and proven theory means that they can be usedwithout giving much thought to their correctness, given that one has faith inthe implementation of the tools.

The following sections are based on Hopcroft et al. (2007) and Aho et al. (2006).

Page 30: A simple aspect-oriented language based on C#etd.dtu.dk/thesis/246031/bac09_17.pdf · Summary This report, titled "A simple aspect-oriented language based on C#" is about my work

18 Theory

4.1 Grammars

The formal definition of the syntax of a programming language is usually givenby a context-free grammar, which is usually represented in Extended Backus-Naur Form (EBNF) or simply the basic BNF. A grammar describes the hierachyof the different constructs of the language, and defines how, for example, astatement can either be an if-then-else-statement or a while-loop, and that awhile-loop consists of a keyword, a condition which is an expression, and abody, which in turn is a new statement.

An example of a piece of a grammar, taken from the C# grammar used in thisproject, is given in example 4.1, where Stm and EmbStm is short for Statementand EmbeddedStatement, respectively, and Expr is short for Expression. Thissmall piece of a grammar shows that a Statement can either be the declara-tion of a constant variable, or an EmbeddedStatement (in the full grammar,a Statement can also be other things). An EmbeddedStatement can then bea Block, which is a block of new statements, a while-loop or an if-statement.Capitalized words are known as non-terminal symbols (or non-terminals), whilenon-capitalized words or words and symbols in citation marks are terminals.A non-terminal can be expanded into a series of other non-terminals and/orterminals, while a terminal symbol can be translated to a token. ”{” and ”}”denote that the sequence of symbols between the curly brackets can be repeated0 or more times, while a sequence of symbols surrounded by square brackets canoccur 0 or 1 time.

Example 4.1Stm → "const" Type "=" Expr { "," ident "=" Expr } ";"Stm → EmbStmEmbStm → BlockEmbStm → "while" "(" Expr ")" EmbStmEmbStm → "if" "(" Expr ")" EmbStm [ "else" EmbStm ]

Each of the lines above is called a production rule, or simply a production. Tothe left of the⇒ is the head of the production, which always consists of a single,non-terminal symbol. To the right is the body of the production, which consistof a string of terminals and non-terminals.

A lexer is usually implemented as a deterministic finite automaton (DFA), whichalso takes an EBNF or a list of regular expressions (regular expressions will bedescribed below) as input. This input is used to tell the lexer how to constructdifferent tokens, so that it knows that a number consists of a string of digits,and an identifier consists of a character followed by a string of characters anddigits.

Page 31: A simple aspect-oriented language based on C#etd.dtu.dk/thesis/246031/bac09_17.pdf · Summary This report, titled "A simple aspect-oriented language based on C#" is about my work

4.2 Finite automata 19

4.2 Finite automata

A finite automaton, such as a DFA mentioned above, is a finite statemachine,consisting of a finite set of states and transitions between the states. Since thescanner part of a lexer is usually implemented as a DFA, I will cover what a DFAis, and how a DFA can be used to determine if a string of symbols represents alegal word in a language.

First, I will introduce some concepts. An alphabet Σ is a finite set of symbols.The alphabet describes which symbols can be used to create strings in a givenlanguage. A string is a finite sequence, perhaps of length 0, of symbols takenfrom the alphabet. If a string is of length 0, we say that it is the empty stringε. A language L is a subset of the set of all possible strings that one can creategiven an alphabet Σ.

A DFA describes such a language. A DFA consists of the following:

1. A finite set of states, Q

2. A set of legal input symbols, the alphabet Σ

3. A transition function, that takes a state q and a symbol a, and returns astate p such that there is a transition from q to p labeled a. The transitionfunction is written as δ(q,a).

4. A single start state, s

5. A set of terminal states, called the final or accepting states, F

This gives us a DFA as the tuple A = (Q,Σ, δ, s, F ) (Hopcroft et al., 2007).This DFA is said to describe the language L(A),

Given a string of symbols from Σ, the DFA starts in the start state, and for eachsymbol, it consumes the symbol and follows a transition with a label matchingthe consumed symbol, if such a transition exists, leading to a new state. Whenall the symbols are consumed, it checks if it ends up in an accepting state.If this is the case, the string is part of the language described by this DFA.The accepting state that the automaton ends up in can be used to differentiatebetween different kinds of strings, such as words or numbers.

A small DFA, ({s1, s2, s3, s4}, δ, s1, {s3}) is illustrated in figure 4.1. The tran-sition function δ is illustrated in the graph as labelled, directed connectionsbetween states. Here, s1 is the start state, s3 is an accepting state illustrated

Page 32: A simple aspect-oriented language based on C#etd.dtu.dk/thesis/246031/bac09_17.pdf · Summary This report, titled "A simple aspect-oriented language based on C#" is about my work

20 Theory

by the double circle, and the transitions are shown as labelled arrows betweenstates. This DFA takes as input symbols from the alphabet {0, 1}, and acceptsall strings consisting of a ”10” followed by an arbitrary sequence of 1’s (10 and1011111111 are both strings in the described language).

s3

s2

s4

s1

1 0

100

1, 0

1start

Figure 4.1: Small example of a DFA

There is also such a thing as a nondeterministic finite automaton (NFA). NFA’sare able to define the same class of languages that DFA’s can, but they are ableto express a language in a more compact way, requiring less states. NFA’s arenondeterministic in the way that for each (state, symbol)-pair, there may beseveral transitions, which enables the NFA to be in several states at the sametime. NFA’s are useful because they are easier to construct than a DFA, andone can always translate an NFA to a DFA. I will not discuss NFA’s further,since they have little relevance for this project.

The languages that DFA’s and NFA’s define is the class of regular languages.Regular languages are a subset of the context-free languages, that can be de-scribed by context-free grammars that I have discussed above. As such, DFA’sand NFA’s are not as powerful as a context-free grammar, but they are sufficientin many cases.

4.2.1 Regular Expressions

Above, I talked about finite automata as a way to define a language of stringsover an alphabet. DFA’s are useful for checking that a string is part of alanguage, but it is difficult to specify a DFA in a compact, declarative way.Luckily, we have another way to concisely declare a regular language: regularexpressions. An example of a (very simple) regular expression, defining the same

Page 33: A simple aspect-oriented language based on C#etd.dtu.dk/thesis/246031/bac09_17.pdf · Summary This report, titled "A simple aspect-oriented language based on C#" is about my work

4.3 Lexical analysis 21

language as the DFA in figure 4.1, is shown in the below example

Example 4.2101*

As we can see, it seems that it is much easier to describe a regular languagethrough a regular expression, than through a DFA.

A regular expression is constructed by combining simpler regular expressionsinto more complex ones, by use of four basic operations: concatenation, alter-nation (or union), closure and grouping. Regular expressions can be definedinductively as follows: (the following definition is based on the definition inHopcroft et al. (2007)).

Definition 4.1Basis:

1. ε and ∅ are regular expressions, denoting the language consisting

of the empty string ε, and the empty language, respectively.

2. Given a symbol a from the alphabet, a is a regular expression

denoting the language consisting of the single string ’a’.

3. L represents any language, so that L(a) is the language described

by the regular expression a.

Induction

1. Union: If E and F are two regular expressions, then E+F is a

regular expression describing the language L(E) ∪ L(F), which

is all strings in L(E), as well as all strings in L(F).

2. Concatenation: If E and F are two regular expressions, then EF is

a regular expression, describing the language L(E)L(F), consisting

of all the combinations one can make by concatenating a string

from L(E) with a string from L(F).

3. Closure: If E is a regular expression, then E∗ is a regular

expression that describes the closure of the language L(E), which

is the set of strings that can be formed by concatenating any

number of strings from L(E), possibly selecting the same string

more than once.

4. Grouping: If E is a regular expression, then (E) is a regular

expression, describing the same language.

4.3 Lexical analysis

When given a file with the source code for a program, the compiler or aspectweaver must first send the stream of charaters through the lexical analyser to

Page 34: A simple aspect-oriented language based on C#etd.dtu.dk/thesis/246031/bac09_17.pdf · Summary This report, titled "A simple aspect-oriented language based on C#" is about my work

22 Theory

group them into a stream of meaningful tokens, which the parser can work with.In this process, the lexical analyser, or lexer, works with the following concepts:

• A lexeme is a sequence of characters representing a token, such as anidentifier or a literal (string literal or number).

• A pattern is a description of how lexemes are constructed. A pattern canbe a production rule in a grammar, or a regular expression. Patterns areused to identify lexemes in a stream of characters.

• A token is a category of lexemes. A token consists of the name of thecategory and a value. When a lexeme is discovered, the pattern determineswhich token it is, and creates a new token of that type, with the lexemeas the value (this is not necessary if the lexeme is a reserved keyword orpunctuation, for example, as they often have their own token name).

An example of a token could be 〈num, 42〉, which would represent the numericliteral 42. Another example could be 〈while〉 or 〈id, ”p1”〉 representing thereserved keyword, while and the identifier p1, respectively.

Actually, the lexical analyser and the parser are working at the same time. Theparser requests the next token from the lexer, which scans forward, finds thenext lexeme, maps it to a token and returns in to the parser. Many parsers alsoinsert the token into a symbol table, which I will not cover here. Figure 4.2 fromAho et al. (2006) shows this interaction.

LexicalAnalyzer

Source program

Parser

LexicalAnalyzer

getNextToken

TokenParse tree

Figure 4.2: Interactions between the lexical analyzer, which provides tokens,and the parser, which requests tokens, and builds a parse tree

Page 35: A simple aspect-oriented language based on C#etd.dtu.dk/thesis/246031/bac09_17.pdf · Summary This report, titled "A simple aspect-oriented language based on C#" is about my work

4.4 Syntax analysis 23

4.4 Syntax analysis

After the lexical analysis, where the source code is transformed from a streamof characters to a stream of more meaningful tokens, the syntax analyser, orparser, takes over. The job of the syntax analyser is to make sure that the sourcecode is syntactically well-formed, and if so, transform it into an intermediaterepresentation, for example in the form of a parse tree.

A parser can be implemented using different strategies. The two primary strate-gies are called top-down and bottom-up parsing. Parser generators usually im-plement a bottom-up parser, but there exists some tools that generate top-downparsers, namely ANTLR (ANTLR, 2009) and Coco/R (Mossenbock et al., 2008).

4.4.1 Top-down parsing

Top-down parsing is an expansive parsing strategy, where the parser takes aninput string, and tries to find a leftmost derivation for that string. Consider thefollowing simple grammar (from Hopcroft et al. (2007)), where E is the startsymbol, upper-case letters are non-terminals and lower-case letters are terminalsymbols.

Example 4.3E → IE → E+EE → E*EE → (E)

I → aI → b

Given the following input string:

a*(a+b*a)

the parser starts with the start symbol E and tries to expand it by replacingit with one of its production bodies. When this is done, it chooses a new non-terminal symbol in the derived string and expands it the same way. This iscontinued until there are no more non-terminal symbols in the string, and the

Page 36: A simple aspect-oriented language based on C#etd.dtu.dk/thesis/246031/bac09_17.pdf · Summary This report, titled "A simple aspect-oriented language based on C#" is about my work

24 Theory

derived string is equal to the input string. If such a derivation is possible, theinput string is a part of the language described by the grammar.

There are two issues: which non-terminal symbol should be expanded in eachstep, and which production should be used to expand it? Top-down parsingusually tries to find a leftmost derivation, which means that it is always theleftmost non-terminal that is selected for expansion. This class of parsers arecalled LL parsers, since they read from the Left to the right, and they find aLeftmost derivation. The parser can decide on the production to use either bytrying one and backtracking if it is wrong, or by looking ahead at the input todetermine which production is the correct.

For the above input string, a leftmost derivation would look like the following:

Example 4.4E ⇒ E*E ⇒ I*E ⇒ a*E ⇒ a*(E) ⇒ a*(E+E) ⇒ a*(I+E) ⇒ a*(a+E)⇒ a*(a+E*E) ⇒ a*(a+I*E) ⇒ a*(a+b*E) ⇒ a*(a+b*I) ⇒ a*(a+b*a)

Note that the above grammar is ambiguous. When expanding the E inside theparanthesis for the first time, the parser can either choose the production E+Eor E*E. This will lead to different parse trees with different meanings. Whendesigning a grammar, one must get rid of ambiguity.

The general approach to top-down parsing is called recursive descent. The ideais that a procedure is written for each non-terminal symbol, where each proce-dure implements the productions that have this symbol as the head. Generalrecursive descent might require backtracking if there are more than one pro-ductions to choose from in a procedure, or it might look ahead at the input todetermine which production to choose. An LL parser that looks ahead is calledan LL(k) parser, if it can look k tokens ahead when parsing an input sequence.A procedure for the non-terminal E above might look like the following:

1 procedure E( ) {2 if ( lookahead (1) == ’a ’ | | lookahead (1) == ’b ’ )3 I ( ) ;4 else if ( lookahead (2) == ’+ ’)5 E() ; match ( ’+ ’) ; E( ) ;6 else if ( lookahead (2) == ’∗ ’ )7 E() ; match ( ’∗ ’ ) ; E( ) ;8 else if ( lookahead (1) == ’ ( ’ ) )9 match ( ’ ( ’ ) ; E( ) ; match ( ’ ) ’ ) ;

10 }

Here, lookahead(n ) is a method that looks n tokens ahead in the input string,

Page 37: A simple aspect-oriented language based on C#etd.dtu.dk/thesis/246031/bac09_17.pdf · Summary This report, titled "A simple aspect-oriented language based on C#" is about my work

4.4 Syntax analysis 25

too see which symbol is there. The match()-method consumes an input tokenand verifies that the value of the token is equal to symbol given as an argument.

Top-down parsing benefits from being an easy way to hand-implement parsers,because the recursive descent strategy is easy to understand and implement,since it follows the structure of the grammar closely.

To create a parse tree when doing top-down parsing is easy, since each non-terminal represents an internal node, and each terminal represents a leaf node.In the top of each of the mentioned procedures, simply create a new node ofthe appropriate type. Each procedure should return the node created, so if, forexample, procedure A is called, it creates a node of type A. It then makes a callto procedure B, which returns a node of type B. This node is then added as achild of procedure A’s node. This way, a parse tree can be built top to bottom.

4.4.2 Bottom-up parsing

The opposite of top-down parsing is bottom-up parsing. Where top-down pars-ing tries to build a parse tree starting with the root, bottom-up parsers try tobuild a parse tree starting with the leaves. It takes a string of terminal symbolsas input, and then tries to reduce these to non-terminal symbols, until the wholestring is reduced to the start symbol of the grammar.

A usual approach to bottom-up parsing is called shift-reduce. A shift-reduceparser works by having a stack, onto which it pushes the input symbols as itreads them. At each step, it looks at the symbols on the stack, and sees if thereexists a production, such that a string of symbols on the stack matches the bodyof the production. If this is the case, the matching symbols on the stack arepopped, and the head of the production is pushed on to the stack again. This isthe reducing-part. If the parser can not do a reduction, it shifts the next inputsymbol on to the stack.

As an example, consider the grammar from before, and the string a * b. Thefollowing shows the parsing process, where the left side shows the unread input,

Page 38: A simple aspect-oriented language based on C#etd.dtu.dk/thesis/246031/bac09_17.pdf · Summary This report, titled "A simple aspect-oriented language based on C#" is about my work

26 Theory

and the right side shows the stack.

Example 4.5a * b [ ]* b [a ]* b [I ]* b [E ]b [E * ]

[E * b][E * I][E * E][E]

If we look at this as a derivation from the start symbol to the input string,we see that this is a rightmost derivation. A bottom-up parser is therefore anLR-parser since it reads the input from Left to Right, producing a rightmostderivation.

Bottom-up parsers are usually harder to implement by hand, but most parsergenerators build LR parsers, since they can describe more languages than LLparsers, and can be very effective when implemented correctly.

4.5 Parse trees

Above, I have discussed the different types of parsers and the basic theory ofhow they work. I have assumed that the job of the parser is to check thesyntax of the input, and build a parse tree for use by the later parts of thecompiler. Sometimes, building a parse tree is not necessary, and a compiler canjust generate code while parsing, or another intermediate representation than atree structure is used. The aspect weaver I am going to build in this project,however, requires a parse tree, so I am going to discuss trees as a datastructure,how they are created and how they may be manipulated.

4.5.1 Structure of a parse tree

A tree is defined as an undirected, connected, acyclic graph (Kleinberg andTardos, 2005). A tree is usually thought of as having a root node, a set ofinterior nodes and a set of leaf nodes. Each node has a set of child nodes,possibly the empty set, and at most one parent. The root node is the only node

Page 39: A simple aspect-oriented language based on C#etd.dtu.dk/thesis/246031/bac09_17.pdf · Summary This report, titled "A simple aspect-oriented language based on C#" is about my work

4.5 Parse trees 27

without a parent, and leaf nodes are the only nodes with no child nodes. Nodeswith both a parent and child nodes are the interior nodes.

A tree structure seem like a natural way to represent the source code for aprogram, after it has been parsed by a parser using a grammar as discussedpreviously. The derivation sequence of a string derived from a context-freegrammar can be more or less directly translated to a tree structure, where thestart symbol is represented by the root node, each non-terminal symbol in thesequence is represented by an interior node in the tree, and each terminal symbolis represented by a leaf node. The childrens of a node are the symbols in thebody of the production that was used to expand that node. For example, thefollowing derivation sequence:

Example 4.6E ⇒ E*E ⇒ I*E ⇒ a*E ⇒ a*I ⇒ a*b

can be translated to the parse tree shown in figure 4.3.

E

EE *

II

a b

Figure 4.3: Small parse tree representing a simple derivation

4.5.2 Tree traversal

Often, it will be necessary to search through the tree or a subtree, for exampleto find a specific node or to find all nodes of a given type. For this, variousgraph search algorithms exist. An example of such an algorithm is Breadth-FirstSearch, or BFS, which is a simple, uninformed search algorithm that starts thesearch in the root of a tree (or the root of a subtree), and searches down onelayer at a time. The algorithm maintains a queue of nodes to visit next, and ineach iteration, it removes the next node from the queue, examines it and finallyadds all the node’s children to the end of the queue.

An alternative to BFS is Depth-First Search, or DFS, which is very similar, butuses a stack instead of a queue. For each iteration, it pops an unvisited node

Page 40: A simple aspect-oriented language based on C#etd.dtu.dk/thesis/246031/bac09_17.pdf · Summary This report, titled "A simple aspect-oriented language based on C#" is about my work

28 Theory

from the stack, examines it, and pushes the node’s children onto the stack. Thisway, it searches to the bottom of the tree, before backtracking to the last branchit encountered, which it then explores to the bottom and so on.

Both these search algorithms have a time complexity that is linear to the numberof nodes, so if we have to search through the entire tree, not looking for a specificnode but rather for all nodes of a specific type, then the performance of thesetwo algorithms should be roughly the same.

4.6 Auto-generated lexers and parsers

Above, I have discussed the theory behind the front-end of compilers, and howlexers and parsers work. One can use the above theory to write a compiler front-end by hand, but tools exist which are able to generate code for a front-end,given a sufficient description of the language. Tools such as lex and the freeversion, flex, take as input a list of regular expressions, and produces the sourcecode for a lexer. It is also possible to specify semantic actions to each regularexpression that is executed whenever an instance of that regular expression isfound in the input.

For parsers, the best known tools are probably YACC (Yet Another Compiler-Compiler) or its free counterpart BISON. These take as input a context-freegrammar denoting a language, and produces the source code for a parser thatis able to parse this language.

Instead of having a tool for the lexer, and another for the parser, one mightchoose a tool that is able to generate both. It is also of interest to find atool that supports more output languages - the language that the generatedlexer/parser is written in. Lex, Flex, YACC and BISON are made for the Cprogramming language, though variants for other languages exist.

ANTLR (ANother Tool for Language Recognition) and Coco/R (COmpilerCOmpiler generating Recursive descent parsers) are examples of these kindsof tools. Both of these tools target a large number of languages1, and they areable to produce a lexer and a parser given a context-free grammar describingthe input tokens as well as the language syntax.

1see ANTLR (2009) and Mossenbock et al. (2008) for a full list

Page 41: A simple aspect-oriented language based on C#etd.dtu.dk/thesis/246031/bac09_17.pdf · Summary This report, titled "A simple aspect-oriented language based on C#" is about my work

Chapter 5

Analysis & Design

In this chapter, I analyse the concepts of aspect-oriented programming, withthe purpose of defining how these concepts are going to be implemented. Istart by describing and defining the different concepts from AOP, such as joinpoints, pointcuts, advice methods, aspects and weaving, as well as discussingand explaining the choices I have made regarding the design of these concepts.After this, I design the aspect weaver itself, by discussing the input languagethat the weaver is going to process, the weaving process itself and finally whatthe output of the aspect weaver should be.

5.1 AOP concepts

In this section, I explore the central concepts of aspect-oriented programming,and see how they apply to this project. I discuss the definition of join points,pointcuts and advice methods and the role they play in AOP, and what it meansto ”weave”. The details on how the different concepts are implemented will bediscussed in Chapter 6. In this chapter, I cover some of the design choices madethat will be important during the implementation. Many of the definitions aretaken from Pal (2003), since AspectJ is considered by many as one of the leadingAOP implementations.

Page 42: A simple aspect-oriented language based on C#etd.dtu.dk/thesis/246031/bac09_17.pdf · Summary This report, titled "A simple aspect-oriented language based on C#" is about my work

30 Analysis & Design

Inspired by Wand et al. (2002), I will try to formalise the concepts a bit, toillustrate how advice is matched to join points through pointcuts. The formalaspects of the following sections are based on Wand et al. (2002), with modifi-cations to match this project.

5.1.1 Join points

A term from computer science that has a central role in AOP is a join point(though the term join point is mainly used in AOP, it is not a new concept).The basic description of a join point is the place ”where things happen”. A joinpoint is a well-defined point in the execution flow of the program. Some commonexamples are method calls, execution of operations, throwing of exceptions,instantiation of objects, etc. (Pal, 2003). Join points are an important conceptin AOP, because they describe the points of execution where advice may betriggered (advice will be explained shortly).

As described in the delimitations section, I have chosen to limit the set of joinpoints to method executions. A method execution encompasses the executionof the method body, from evaluation of the arguments to the return of a value.A join point may contain other join points, if the body of a method includes acall to another method. If a method calls itself recursively, then each methodcall constitutes an individual join point, which means that advice methods willbe triggered at each call, if applicable.

A join point in my aspect weaver should make some information available basedon the following. I assume there exists a set of join points JP. Since join pointsare defined to be methods, and methods are represented as subtrees in the parsetree for the C# program, then JP is equal to the subset of nodes in the parsetree which are the method nodes.

Definition 5.1A join point jp ∈ JP is a tuplejp ::= 〈k, pname, v∗〉where k is the type of the join pointk ::= pcall

where pcall denotes a method call, pname is the name of thejoin point and v∗ is the list of arguments for that join point.

For example, the join point 〈pcall, f, (v1, v2)〉 describes a call to method f withthe arguments (v1, v2). This kind of information is available to any advicemethods triggered by this join point.

Page 43: A simple aspect-oriented language based on C#etd.dtu.dk/thesis/246031/bac09_17.pdf · Summary This report, titled "A simple aspect-oriented language based on C#" is about my work

5.1 AOP concepts 31

5.1.2 Pointcuts

With the definition of join points above, we now move on to the related conceptof pointcuts. A pointcut is basically a predicate that describes a set of joinpoints. Advice methods use pointcuts to define which join points the givenadvice should execute at.

In AspectJ, which is the main source of inspiration for this project, the point-cut definition supports some predicate logic, such that it is possible to combinedifferent pointcuts into new ones. For example, if

call(ClassA.MethodB)

and

call(ClassA.MethodC)

are two pointcuts describing calls to, respectively, a procedure MethodB in aclass ClassA, and a procedure MethodC in class ClassA, then

call(ClassA.MethodB) && call(ClassA.MethodC)

is also a pointcut, that describes the set of join points consisting of methodcalls to the methods MethodB and MethodC in a class ClassA.

Further, AspectJ includes some temporal operators, such as cflow(PointCut),which describes all join points in the control flow of a join point jp picked out byPointCut (Pal, 2003). This enables one to apply advice to each execution pointin a method, for example. These operators are not included in this project.

A pointcut designator pcd is syntactically defined by the following:

Definition 5.2pcd ::= "pname" | pcd "&&" pcd | pcd "||" pcd | "!"pcd

This means that a pointcut designator is either described by a call to a joinpoint pname, a conjunction or disjunction of two pointcut designators or thenegation of a pointcut designator. This way, one can combine pointcuts to saythings like ”the execution of all methods called ’test’ or ’debug’”, or ”all joinpoints except the method ’main’”.

Pointcuts have a fundamental operation, which is to determine if a join pointmatches the predicate specified by the pointcut. We define this operation as the

Page 44: A simple aspect-oriented language based on C#etd.dtu.dk/thesis/246031/bac09_17.pdf · Summary This report, titled "A simple aspect-oriented language based on C#" is about my work

32 Analysis & Design

function match-pcd with the following basic operation:

Definition 5.3match-pcd("pname", 〈k, pname′, v∗〉)

=

{true if k = pcall ∧ pname = pname′

false otherwise

This says, that a pointcut matches a join point, if the join point is a methodcall, and the method is the same name as specified in the pointcut. The functionreturns true if the pointcut and the join point matches, and false otherwise.

The boolean operators on pointcut designators are defined as follows:

Definition 5.4match-pcd(pcd1 && pcd2,jp) =

match-pcd(pcd1, jp) ∧ match-pcd(pcd2, jp)

match-pcd(pcd1 || pcd2,jp) =match-pcd(pcd1, jp) ∨ match-pcd(pcd2, jp)

match-pcd(!pcd,jp) = ¬(match-pcd(pcd, jp))

These simply state that if the join point matches two pointcuts, it matchesthe conjunction of those pointcuts; if a join point matches one or both of twopointcuts, it matches the disjunction of those; and if a join point matches apointcut, it does not match the negation of that pointcut.

5.1.3 Advice methods

Advice methods are the third part of aspect-oriented programming languages.An advice method consists of three components: a pointcut, which defines whichjoin points this advice is tied to; a piece of code that is executed at the relatedjoin points; and a position, which state when, in relation to the join point, thecode is executed. The associated pointcut and position are grouped together inthe head of the advice method, and the code to be executed is in the body.

There are three types of position and advice can have, called ”before”, ”after”and ”around”, named after the execution of the advice body relative to the joinpoint. With before-advice, the advice body is executed before the join point,after-advice is executed after the join point, and around-advice is executed bothbefore and after the join point, with the extra ability to control and influencethe execution of the join point itself. The different positions have different

Page 45: A simple aspect-oriented language based on C#etd.dtu.dk/thesis/246031/bac09_17.pdf · Summary This report, titled "A simple aspect-oriented language based on C#" is about my work

5.1 AOP concepts 33

uses. Before-advice can for example be used to make sure that every methodcall is logged to a file, or it can make sure that a method is only called byusers with appropriate access control levels. After-advice can be used to releasesystem resources after a join point is done using them, and around-advice canfor example be used to implement a ”design-by-contract”-pattern, where theadvice checks that the precondition of a method is satisfied before the method isexecuted, and checks that the postcondition is also satisfied after the execution.The around-advice method then has the ability to stop the join point fromexecuting, for example if the precondition is unsatisfied, and it can cast anexception if the postcondition is unsatisfied.

A single advice method can have defined several positions at the same time.For example, one can imagine an advice method that should be executed beforesome set join points, and after another set.

After-advice

Before-advice is pretty easy to understand: it executes before the join point.After-advice is also pretty simple, but has some issues. As I have noted, joinpoints are the set of method executions. A method can return in two ways: bya return statement, or by throwing an exception. Should the after-advice beexecuted after return statements, when an exception is thrown, or both? Onesolution is to create three types of after-advice: afterReturning, afterThrowingand afterBoth.

I will only create the afterReturning type, where advice runs after the methodreturns normally, but I will try to make it as easy as possible to implement theother two types.

Around-advice

There are some considerations to be made regarding the around-advice. Before-and after-advice is relatively straightforward, as described above. Around-advice, on the other hand, raises some questions that need to be addressed.How does the programmer specify what code executes before the join point,and what executes after? It would be nice if the programmer could controlwhether the join point is executed at all, so how should this be done? If theadvice method decides that the join point should not be executed, how does theprogrammer deal with any return values that the calling code might expect? Iwill address these questions here, and then go into more details of how these

Page 46: A simple aspect-oriented language based on C#etd.dtu.dk/thesis/246031/bac09_17.pdf · Summary This report, titled "A simple aspect-oriented language based on C#" is about my work

34 Analysis & Design

solutions are implemented in Chapter 6.

First, how does the programmer specify which piece of advice is run before andafter the join point? A solution is to let the programmer create two advicemethods, and specify that one should be executed before, and the other after,using regular before- and after-advice. This, however, conflicts with the desireto be able to stop a join point from executing. Another solution is to have theadvice in one body, and then use some kind of language construct to separate thebefore-advice from the after-advice, and to let the aspect weaver know when thejoin point should be executed. This could for example be some kind of specialstatement or keyword proceed, that when reached, will execute the join point.This way the programmer can write some advice, then this keyword, and thenthe rest of the advice. If the keyword is omitted, or placed such that it maynot be reached (for example in an if-then-else construct), then the join pointmay not be executed. This gives the programmer the desired control over joinpoints. This keyword also allows the advice method to execute the join pointsevaral times, by having multiple proceeds inside the advice body.

This solved two of the three issues. But what happens if the proceed-keywordis not reached? If the type of the join point is a method execution (which I havelimited the set of join points to), then the method from which this method callcame will likely be expecting a return value. The best solution to this, is tostate a requirement to the programmer, that the around-advice method shouldhave a return type equal to the join points it matches, or a more abstract type,and then let the programmer deal with the problem of returning an appropriatevalue. If the proceed-keyword returns the value of the method at the join pointsomehow, the programmer can then either use that value as return value to theoriginal method caller, or create his own.

The proceed-keyword creates one problem - it only has a defined meaning inaround-advice. As I noted above, a single advice method can have more thanone position, but this conflicts with the around-advice having a special keyword,that only has meaning for this position. The solution to this is to allow anadvice method to have the positions ’before’ and ’after’ at the same time, butnot ’before’ and ’around’, or ’after’ and ’around’. This means that an advicemethod can be ”before” one pointcut p1, ”after” another pointcut p2 and then”before” some third pointcut p3, but it can not be ”around” a fourth pointcutp4. Another advice method can, though, be ”around” pointcut q1 and q2.

Page 47: A simple aspect-oriented language based on C#etd.dtu.dk/thesis/246031/bac09_17.pdf · Summary This report, titled "A simple aspect-oriented language based on C#" is about my work

5.1 AOP concepts 35

5.1.4 Aspects

The previous three sections have described join points, pointcuts and advicemethods, which are the important concepts of any aspect-oriented language.Since AOP is a complement to object-oriented programming, and the goal is tomake separation of concerns easier, so that aspects of the program become moremodular and encapsulated, it would be obvious that some sort of structure toencapsulate advice methods and pointcut designators would be beneficial. Sucha construct is called an aspect (I use the typewriter font to differentiate betweenthe language construct aspect, and the concept of aspects in the general sense),and is to AOP, like a class is to OOP. The purpose of an aspect is to encapsulateall the advice methods and pointcut designators that relate to a particular aspectof the program.

5.1.5 thisJoinPoint

When an advice method is executed, it is useful if the programmer can get somerelevant information about the specific join point that the advice is intercepting.As defined previously, the set of join points in a program is equal to the set ofmethods, so interesting information could be

• The name of the method

• The visibility of the method (public/private/protected)

• The return type of the method

• Information about the class this method is a member of

• The list of arguments passed to the method

• A reference to the code that called this method

• The number of times this method has been called

All this information can be made available to the programmer through an ob-ject, offering a list of static fields, each responsible for a piece of information.This object, called thisJoinPoint, is not implemented in a library, but a stubconsisting of only the fields that may be referenced. It is then up to the weaver tofind references to these members of thisJoinPoint and replace them with therelevant information. For example, if an advice method contains a reference tothisJoinPoint.MethodName, the weaver replaces the reference with the actualname of the join point. More details on how this is implemented is discussed inthe next chapter.

Page 48: A simple aspect-oriented language based on C#etd.dtu.dk/thesis/246031/bac09_17.pdf · Summary This report, titled "A simple aspect-oriented language based on C#" is about my work

36 Analysis & Design

5.1.6 Weaving

Up until now, I have discussed different language features, such as pointcuts,advice methods and aspects. This section will deal with the process of takingadvice methods and their pointcut designators, and tie them to the matchingjoin points, thereby modifying the original program with the code specified inthe advice methods. This process is called weaving.

Weaving is defined as

”The process of executing the relevant advice at each join point”

(see Wand et al., 2002).

The above quote defines the purpose of weaving. However, it says nothingabout how the weaving should be done. This section will discuss some of thedifferent methods of weaving, and will be used to decide which method will beimplemented in this project.

I will describe two different forms of weaving: source-level weaving and bytecodeweaving, since these are two simple and useful approaches to weaving. AspectJstarted by offering source-level weaving, but moved over to bytecode weaving,since this allows the programmer to write aspects to already compiled code.

Source-level weaving

Source-level weaving is used during or before compile-time, and requires accessto the source code of the program. Source-level weavers function as a prepro-cessor, reading the aspects and the regular program code and modifying thecode, resulting in a new program that can be passed to the regular compiler.This concept resembles the way that Stroustrup created C++, by writing a pre-processor that converted C++ (or C with Classes, as it was called at first) intoC, and then using a standard C compiler (Stroustrup, 2009).

Source-level weaving can, in practice, be done by parsing the original programas well as the aspects, and then modify the intermediate representation (IR),for example in the form of a parse tree, before converting the IR back to sourcecode, and passing this to the compiler. Thus, source-level weaving only requiresknowledge of the language itself, but requires that the weaver has access to thesource code, and the process can only happen at compile-time.

Page 49: A simple aspect-oriented language based on C#etd.dtu.dk/thesis/246031/bac09_17.pdf · Summary This report, titled "A simple aspect-oriented language based on C#" is about my work

5.1 AOP concepts 37

Bytecode weaving

Bytecode weaving on the other hand, can be used for languages that run on avirtual machine, such as Java (which runs on the Java Virtual Machine, JVM)or C# or other .NET languages (which run on the Common Language Runtimevirtual machine). These languages are compiled into bytecode form, and thisrepresentation is then interpreted by the virtual machine. Bytecode weavers takean already compiled program, and then weave the advice into the bytecode. Thisapproach does not require access to the source code, only to the compiled code inbytecode form. This means that weaving can be done later in the deploymentprocess, as late as just before the code is loaded by the virtual machine. Italso means that the weaver can target more languages, since it works with thebytecode instead of the original code. This means that all languages that compileto the same bytecode can be targeted by the same weaver. This is especiallyuseful on the .NET platform, since a lot of languages are built on this platform.

Choice of weaving method

The two different approaches to weaving described above each have their ad-vantages and disadvantages. From a usage standpoint, bytecode weaving seemsto perform better: it can be applied after compile-time (for example, at classloading time), it can target more languages, and some things are easier to doon bytecode than on source code1. Bytecode is hard to work with and un-derstand though, and working with bytecode makes it harder to integrate anaspect weaver with a development environment. Source-level weaving on theother hand seems easier to implement, but provides less functionality for theprogrammer. It requires no knowledge of bytecode, but requires a front-end forthe target language. However, a lot of tools are available that can help createsuch a front-end.

I have chosen to implement a source-level weaver. The reasons for this is that Ithink it will enable me to put more effort into the AOP aspects of this project,and use less resources on learning the details of virtual machines and bytecode.It is also my estimation that source-level weaving will be more than adequate tocreate a simple language that will serve to illustrate basic AOP concepts, and beusable in small projects. The disadvantages with source-level weaving are notso significant, that further development on my aspect weaver will be hamperedby this decision.

1see Hugunin (2003), by AspectJ codesigner, Jim Hugunin

Page 50: A simple aspect-oriented language based on C#etd.dtu.dk/thesis/246031/bac09_17.pdf · Summary This report, titled "A simple aspect-oriented language based on C#" is about my work

38 Analysis & Design

5.2 Design

In the previous part of this chapter, I have defined and analysed the relevantconcepts from aspect-oriented programming, with the objective of making itclear how these concepts are meant to be implemented. I will now take a stepback and discuss the design of the overall structure of the aspect weaver I amgoing to implement.

The purpose of the aspect weaver is to weave together normal C# and aspectcode. I start by defining this aspect language, which will be based on C#, butwith some new semantics. I then go over the weaving process, designing theoverall architecture and discussing, in detail, every step of the process. Finally,I round this section off with a discussion on the output of the aspect weaver,and how it is going to be used.

5.2.1 Input language

The idea behind an aspect weaver is to take the aspects and the ”regular”code and weave them together, as defined earlier. This section will describehow aspects2 are specified by the programmer. I will call this language the”aspect language”, even though, as we will see, it has the same syntax as C#.

My aspect weaver is meant to target C# code. Therefore, it makes most sensethat the aspect language is based on C#. An alternative would be, if the weavercould target CIL, the .NET intermediate language. Then, the aspect languagecould be build on any .NET language, but the goal of this project is to build asimple aspect-oriented language based on C#, as described previously.

First, the language needs a way to specify what is an aspect, pointcut designatorand advice method. An idea is to create new language constructs for these,which could be designed to fulfill the needs of the aspect language. The threeconcepts are conceptually close to existing C# constructs, though. An aspectis like a class, in the way that it encapsulates pointcut designators and advicemethods, the same way a class encapsulates attributes and methods. A pointcutdesignator is simply an expression defining a set of join points. These canbe declared using standard variables, for example a string. Advice methodsare simply methods with some extra information in the method signature (theassociated pointcut), as well as some special properties. Therefore, another ideais to use these standard constructs, but specify that they are aspects, pointcuts

2Remember that aspects, when written in the typewriter font, refers to an aspect in theprogramming sense, like a class or an interface

Page 51: A simple aspect-oriented language based on C#etd.dtu.dk/thesis/246031/bac09_17.pdf · Summary This report, titled "A simple aspect-oriented language based on C#" is about my work

5.2 Design 39

and advice methods, respectively. This can be specified, for example, by usingC# attributes (the equivalent of Java annotations). A C# attribute is a form ofsyntactic metadata, which is compiled along with the rest of the code, but doesnot do anything by itself. The attribute can normally be queried by the codeat runtime through reflection, but in the case of my aspect weaver, it should bepossible to assign some semantics to attributes, since I am going to parse theaspect code.

I have chosen to implement aspects and advice methods as standard classesand methods, but annotated by special attributes. There are two reasons forthis. This means that there is no need to extend the syntax of C# with newlanguage constructs. By doing this, it should be easier to get started with usingthe language, since it looks like regular, annotated C#. Also, it should bepossible to compile the aspect language using a standard C# compiler, withoutusing an aspect weaver. This will, of course, not do anything, since no weavingwill be done, but if one wants to test the code unwoven, one can simply use justthe compiler instead of the weaver and the compiler. This might be useful whendoing unit testing, first testing the unvowen code, and then testing the wovencode.

To illustrate how the aspect language is going to look like, I am going to show asmall code sample, including a declaration of an aspect, a pointcut designatorand an advice method.

1 namespace Program {2 [ Aspect ]3 class AspectClass {4 [ PointCut ]5 const string p1 = "m" ;6 [ PointCut ]7 const string p2 = "n" ;8

9 [ Before ( p1 ) ]10 public void beforeAdvice ( ) {11 // do something that needs to be done before m ()12 }13

14 [ Around (p2 ) ]15 public void aroundAdvice ( ) {16 // do something before and after n ()17 }18

19 [ Before ( p1 ) , After ( p2 ) ]20 public void beforeAndAfterAdvice ( ) {21 // do something before p1 , and after p222 }23 }24 }

Page 52: A simple aspect-oriented language based on C#etd.dtu.dk/thesis/246031/bac09_17.pdf · Summary This report, titled "A simple aspect-oriented language based on C#" is about my work

40 Analysis & Design

This is a regular C# program, that uses annotations to apply some specialsemantics to different pieces of the code. For example, the [Aspect]-annotationin line 2 tells the aspect weaver that this class is an aspect, lines 4 and 6 tellthat the below string is a pointcut and the annotations in lines 9 and 14 denotethat these methods are before- and around-advice methods, respectively. Theannotation in line 19 denotes that the advice has multiple positions declared, asdiscussed earlier.

If this code is passed to a normal C# compiler, it will do nothing, but thecompiler will not complain. The annotations allow the aspect weaver to analysethe code, however, and see that this is part of the aspect code, and should betreated as such.

The aspect weaver takes the aspect and C# code, and passes through a lexerand a parser to build two parse trees. While doing this, it builds a table of alljoin points, pointcuts and advice methods. When this is done, the parse treeand the tables are passed to the aspect weaver.

5.2.2 Weaving process

The previous section described the input language of the aspect weaver. Thissection describes the architecture of the solution, by showing some process di-agrams to illustrate the different steps the aspect weaver has to go through,and a class diagram to show the different components of the weaver, with adescription of each component.

The job of the aspect weaver is to take the C# and aspect code, weave themtogether and then produce some output that can be compiled to executablebytecode. As mentioned previously, I have chosen that the aspect weaver willoutput C# code, which will be passed to a normal C# compiler for further com-pilation. This choice will be discussed in the next section. A general overviewof the aspect weaver is shown in figure 5.1.

This figure shows the idea behind the weaving process. First, the programmerwrites C# and aspect-code. This is passed to the aspect weaver, which weavesthe two together. The weaver then generates intermediate C# code, which ispassed directly or indirectly to a C# compiler, for example csc, which is Mi-crosoft’s standard C# compiler. This then generates a program in the CommonIntermediate Language, which can be interpreted by the .NET virtual machine.This section will focus on what happens in the box labeled ’Weaver ’.

Receiving two parse trees, one for the aspect code and one for the C# code, as

Page 53: A simple aspect-oriented language based on C#etd.dtu.dk/thesis/246031/bac09_17.pdf · Summary This report, titled "A simple aspect-oriented language based on C#" is about my work

5.2 Design 41

C# code

Weaver

Aspectcode

C# code csc

Compiledbytecode

Figure 5.1: Overview of the weaving process

well as a table containing references to all join points and pointcuts, the weaverwalks through a series of steps to weave the advice into the C# code. Foreach advice method, it needs to look at the associated pointcut designator(s),find all matching join points, make sure that the advice is injected at the rightspot and modify the advice method, so that all references to members of thespecial object thisJoinPoint are exchanged with the meaningful informationmade available by the join point, as defined previously. The parse trees flow,so to say, through a couple of transformations, resulting in the two parse treesrepresenting the final woven program. This is shown in the diagram in figure5.2.

5.2.3 Output

Finally, when the weaving is done, some output should be produced. The endgoal is to have some executable file, which can be run by the end user. Above,I have described the weaving process and how, in the end, we have the finalprogram in the form of two parse trees.

Generally, compilers take the source code for a program, create a parse tree asan intermediate representation, and then use it to generate the target code. Itwould then make sense to take the parse trees above, and use them to generatetarget code immediately. This, however, would require me to either implementor integrate an existing compiler back-end into the aspect weaver. Since buildinga full compiler is beyond the scope of this project, I have chosen the simplerpath of simply converting the parse tree back to C# code. This code can thenbe passed to an existing compiler, so it can be turned into an executable.

Page 54: A simple aspect-oriented language based on C#etd.dtu.dk/thesis/246031/bac09_17.pdf · Summary This report, titled "A simple aspect-oriented language based on C#" is about my work

42 Analysis & Design

Aspect parsetree

C# parsetree

Find all advicemethods and

match topointcuts

Handle before-and after-advice

Handle around-advice

Output C# code

Figure 5.2: The weaving process in more detail

This conversion from parse tree to C# code is relatively straightforward. Theparse tree already resembles C# code, so it is possible to generate the C# codeby a simple walk through the tree, and implementing a method that is able totake a node as input and give the code represented by that node as output. Anexample of such a method for the if-then-else-statement is shown below. Thismethod takes the root of a subtree representing an if-then-else-statement.The Condition represents the condition of the if-statement. EmbeddedState-ment is the root node of a subtree containing the statements to be executed ifthe condition is true, and finally, the ElseStatement, which is also an embeddedstatement, is the root of a subtree containing the statements to be executed ifthe condition is false (the ’else’-part), if such statements are specified.

1 string ToCode ( ) {2 s += " if (" + Condit ion . ToCode ( ) + ")\n {\ n" ;3 s += EmbeddedStatement . ToCode ( ) ;4 s += "\n }\ n" ;5 if ( ElseStatement != null )6 s += " else {\ n" + ElseStatement . ToCode ( ) + "\n }\ n"7 return s ;8 }

Page 55: A simple aspect-oriented language based on C#etd.dtu.dk/thesis/246031/bac09_17.pdf · Summary This report, titled "A simple aspect-oriented language based on C#" is about my work

5.2 Design 43

This method contains calls to the ToCode-method of the children, which mightcontain similar calls to their children and so on, until the bottom of the tree isreached.

If ToCode-methods are implemented for each type of node, a call to the rootnode’s ToCode-method is enough to output the entire tree as C# code.

5.2.4 Class diagram

Weaver

- DiscoverAdviceMethods() - ModifyAroundAdviceMethods() - ModifyOtherAdviceMethods() - CreateMessageCallNode() - ModifyAdviceMethod()

Advice

- AdviceName : string - AdviceClass : string - AdviceNameSpace : string - AdvicePosition: int - MethodParameters: Table + Matches(JoinPoint)

* advicemethodsTreeNode

+ Children : TreeNode [0..*] + Value : Node + Parent: TreeNode + ToCode() + ToString() + Clone()

IfNode WhileNode ForNode

* joinpoints

1 advicemethod

PointCut

+ Scope + PointCutDesignator + ValidatePointCut()

1 pointcut

Scanner

Parser

* pointcuts

Figure 5.3: Class diagram for the aspect weaver

Figure 5.3 shows a (simplified) class diagram for the aspect weaver. The differentcomponents and their responsibilities are:

• The Weaver is the central class. It invokes the parser, getting a list of

Page 56: A simple aspect-oriented language based on C#etd.dtu.dk/thesis/246031/bac09_17.pdf · Summary This report, titled "A simple aspect-oriented language based on C#" is about my work

44 Analysis & Design

advice methods and pointcuts from the aspect source file and a list of joinpoints from the C# source file, as well as two parse trees, representingthe aspect code and the C# code. It then weaves these two parse treestogether.

• The Parser invokes the scanner, which it requests tokens from, and parsesthe input, returning a parse tree.

• The Scanner scans the input file, returning tokens to the parser on request.

• The Advice encapsulates the information regarding an advice method. AnAdvice-object is created for each advice method encountered in the aspectcode, and it holds information about the name of the advice method, theaspect (class) and namespace it is a member of, the type (position) ofthe advice and the argument list that the weaver creates for this advicemethod. It also contains a method that determines if a join point ismatched by the pointcut associated with this advice.

• The TreeNode is the main component of the parse tree. It has a list ofchildren as well as a parent, and it has some information, stored in aninstance of the Node-object. Specialisations of the TreeNode exists, suchas the IfNode, WhileNode and ForNode. Each has the ability to generatethe code represented by the subtree of which this node is the root.

• The PointCut represents a pointcut declaration, keeping track of the scopeof the declaration, as well as the value of the pointcut. When declaringa pointcut, it is validated by a regular expression, which also parses thepointcut designator.

5.3 Chapter Summary

In this chapter, I have analysed the different concepts of aspect-oriented pro-gramming, with the purpose of defining how they should be implemented. Ihave discussed the concepts of join points, pointcuts, advice methods, aspectsand weaving, and I have introduced the special construct thisJoinPoint, whichexposes relevant information about a join point to the advice methods.

I have discussed the different positions of advice methods: before, after andaround. The different positions are used to describe where an advice should beexecuted in relation to the join point. The around -advice position also gets thebenefit of the special procedure thisJoinPoint.proceed(), which allows it tocontrol the execution of the join point — deciding if it should be executed morethan one time, or if it should be executed at all.

Page 57: A simple aspect-oriented language based on C#etd.dtu.dk/thesis/246031/bac09_17.pdf · Summary This report, titled "A simple aspect-oriented language based on C#" is about my work

5.3 Chapter Summary 45

I have described the design of the aspect weaver, by designing the input lan-guage, the weaving process and the output. As input, the aspect weaver takesa C# program and an aspect program. During the weaving process, it parsesthe input, building two parse trees. It then weaves the two parse trees together,before finally outputting a compilable C# program. A class diagram is used toshow the different parts of the aspect weaver, and how they are connected.

Page 58: A simple aspect-oriented language based on C#etd.dtu.dk/thesis/246031/bac09_17.pdf · Summary This report, titled "A simple aspect-oriented language based on C#" is about my work

46 Analysis & Design

Page 59: A simple aspect-oriented language based on C#etd.dtu.dk/thesis/246031/bac09_17.pdf · Summary This report, titled "A simple aspect-oriented language based on C#" is about my work

Chapter 6

Implementation

This chapter describes the implementation of the practical side of this project -the aspect weaver. In the previous chapter, I described the overall architectureof the aspect weaver through a couple of simple process diagrams and a classdiagram. This chapter goes into more detail with the different processes, by de-scribing how the parse tree is built and how the weaving process is implemented.

6.1 Tools and datastructures

In this section, I discuss the tools and datastructures I have used during theimplementation. As noted previously, the parse tree plays a significant role inthe aspect weaver, so I am going to discuss how it is generated, and describe itsstructure.

I have also mentioned that in order to build a parse tree, the source code needsto be fed through a scanner and a parser. To avoid spending a lot of time on im-plementing these tools, I have used a program1 to automatically generate them

1I will refer to this as a parser generator, even though it will generate both a scanner anda parser

Page 60: A simple aspect-oriented language based on C#etd.dtu.dk/thesis/246031/bac09_17.pdf · Summary This report, titled "A simple aspect-oriented language based on C#" is about my work

48 Implementation

from a formal grammar, as described in Chapter 4. I will start by discussingthe choice of parser generator.

6.1.1 Parser generator

Several parser generators exist today, and many have been on the market formany years. Traditionally, parser generators have been written in C/C++,and used those languages as output language, but there are parsers for manydifferent languages like C#, Java, Lisp, Haskell, Pascal and Python, to namea few. The output language of the parser generator does not determine whatkinds of language the generator can generate parsers for, but it does influencehow easy it is to integrate the generated parser with the rest of the program.Since I am writing the aspect weaver in C#, it makes most sense to use a parsergenerator that can output to C#.

Another thing to consider, when choosing a parser generator, is the existanceof a premade, free to use C# grammar for that tool. It is, of course, possible towrite a C# grammar from scratch (the C# formal grammar is available fromMicrosoft at msdn.microsoft.com), but there is no need to reinvent the wheel,so to speak, when that is not the focus of this project.

Further, support and good documentation are of course two important aspectswhen selecting the tool to work with.

After searching for different parser generators that fulfilled the above require-ments, I ended with two to choose from: ANTLR (ANTLR, 2009) and CoCo/R(Mossenbock et al., 2008). ANTLR had the benefit of providing a C# grammar,with added semantic code to build an abstract syntax tree, but unfortunately,this grammar was incompatible with the newest version of ANTLR, v. 3.0.Coco, on the other hand, had a grammar for C#, but without the semanticactions for parse tree generation.

I decided to use Coco as my parser generator, which would require me to addsemantic actions to the grammar in order for the parser to be able to build aparse tree. This had the advantage that I would have control of how the parsetree was going to look like, since I would be designing the structure.

Coco/R takes a context-free grammar for the lexical and syntactical parts of thelanguage, and produces a scanner and a parser. The parser is an LL(k) parser,using recursive descent.(Mossenbock, 2006)

Page 61: A simple aspect-oriented language based on C#etd.dtu.dk/thesis/246031/bac09_17.pdf · Summary This report, titled "A simple aspect-oriented language based on C#" is about my work

6.1 Tools and datastructures 49

6.1.2 Parse tree

With the parser generator chosen, the next action is to modify the input gram-mar with semantic actions, so that the parser can build a parse tree. Coco/Rallows semantic actions in the form of small pieces of code written in the targetlanguage, which are written in the input file with the formal grammar. Coco/Rcopies these pieces of code to the place in the generated parser where it hasbeen specified in the grammar. As an example, consider the following piece ofa grammar taken from the C# grammar that follows with Coco/R:

1 PointerOrArray<out TypeKind type , TypeKind curType , out int dims>2 ( . type = curType ; dims = 0 ; . )3=4 { IF ( IsPointerOrDims ( ) )5 ( "*" ( . type = TypeKind . po in t e r ; . )6 |7 "[" ( . dims = 1 ; type = TypeKind . array ; . )8 { " ," ( . dims++; . )9 } "]"

10 )11 }12 .

The pieces of code between ”(.” and ”.)” are considered semantic actions byCoco/R.

For this piece of the grammar, the parser generator generates the followingmethod:

1 void PointerOrArray ( out TypeKind type , TypeKind curType , out int ...dims ) {

2 type = curType ; dims = 0 ;3 while ( IsPointerOrDims ( ) ) {4 if ( l a . kind == 118) {5 Get ( ) ;6 type = TypeKind . po in t e r ;7 } else if ( l a . kind == 98) {8 Get ( ) ;9 dims = 1 ; type = TypeKind . array ;

10 while ( l a . kind == 88) {11 Get ( ) ;12 dims++;13 }14 Expect (114) ;15 } else SynErr (184) ;16 }17 }

Page 62: A simple aspect-oriented language based on C#etd.dtu.dk/thesis/246031/bac09_17.pdf · Summary This report, titled "A simple aspect-oriented language based on C#" is about my work

50 Implementation

While the generated method is hard to understand, since it uses a lot of numer-ical identifiers for different tokens, we can see that the semantic action from thegrammar, line 2 is copied to the top of the method at line 2, since this semanticaction should occur before anything else. The code at line 6 in the generatedmethod matches the semantic action on line 5 in the grammar. This code isexecuted after the parser recognises the ”*” token.

Using these semantic actions, it is possible for the parser to create a parse tree.The idea is, each time a new production rule is invoked, to create a new treenoderepresenting this nonterminal, and add it to the tree in the appropriate place.Identifiers, when encountered, should be added as leaf nodes to the tree.

I have created a tree structure that is close to the above description. Thedifference lies in the fact that not every non-terminal or terminal symbol requiresits own node in the tree. Take, for example, a subtree representing a method.This subtree would have a root, stating that this is a method. This root wouldhave some children, one for each terminal symbol in the method signature, suchas private, void, the name of the method, the arguments, paranthesis etc. Oneof these children would be a Block, which would have 2 children representingcurly braces, and one child representing the subtree which would consist of allthe statements in the method. An idea of how this might look is given in figure6.1.

Method

“private” “void” “m” “(“ “int“ “a“ “)“

“{“

Block

“}“Statements

Figure 6.1: A subtree from a parse tree representing a method

To simplify this a bit, I have decided to put more information into each node, atthe expense of the number of nodes in the tree. Many of the terminal symbolsin the method signature are stored as information in the Method-node, andparanthesis and curly braces are implicit. The new parse tree for the abovemethod may look more like the tree in figure 6.2. This makes it easier toextract information from the tree, since the name of the method is stored in afield in the root of the method subtree, instead of it being stored as a child ofthat root.

Page 63: A simple aspect-oriented language based on C#etd.dtu.dk/thesis/246031/bac09_17.pdf · Summary This report, titled "A simple aspect-oriented language based on C#" is about my work

6.1 Tools and datastructures 51

MethodName: “m”Keywords: {“private”, “void”}Arguments: {“int a”}

Statements

Figure 6.2: A simpler subtree from a parse tree representing a method

The nodes in the parse tree are represented by instances of a TreeNode-class.Several derived classes exist for various language constructs, such as IfNode,WhileNode and ForNode, which are used to represent the root of a subtree forthese language constructs. They all inherit from the TreeNode-class, where thechild nodes are stored in a list, but they differ by the fact that the child nodes arealso stored in special fields, so they are easier to access. The IfNode-class, forexample, has a field called Condition, which holds an instance of the TreeNoderepresenting the expression in the condition of the if-statement. This expressionis also stored in the if-nodes list of children, which makes it easy to traverse theparse tree, while also making it easy to find a specific child of a node.

6.1.3 Symbol table

A compiler usually builds and uses a symbol table. A symbol table is a datastructure that holds information about the different symbols encountered inthe program while parsing. This involves information on types of variables,identifiers, scope, etc.

There are 3 entities in the program source that are of interest to the aspectweaver:

• Join points

• Pointcuts

• Advice methods

Page 64: A simple aspect-oriented language based on C#etd.dtu.dk/thesis/246031/bac09_17.pdf · Summary This report, titled "A simple aspect-oriented language based on C#" is about my work

52 Implementation

and information about them should be discovered and stored somehow. Joinpoints and advice methods are stored in lists, and pointcuts are stored in a table,where the key serves to identify the pointcut as well as declaring its scope, andthe value is the value of the pointcut.

The three structures are generated while parsing the C# source. When parsingthe C# code, each time a join point (a method declaration) is encountered, itis added to the list of join points. While parsing the aspect source, when adeclaration of a variable is encountered, it is checked whether it is a field in aclass, and if it is a pointcut declaration. This is the case either if it is of typePointCut, or if it is of type const string with an attribute (annotation) thatspecifies it is a pointcut: [PointCut]. If this is the case, a PointCut-object iscreated and added to the table of pointcuts, with the identifier as key and thepointcut value as value. If a method declaration is encountered, it is checkedwhether a Before, After or Around attribute is specified for this method. Ifthis is the case, an Advice-object is created and added to the list of advicemethods. As noted earlier, an advice method may have several lines in theheader with multiple types and as many pointcuts. To make things simple, anAdvice-object is created for each line in the header, so if a header consists of theline [Before(p1), Before(p2), After(3)], three Advice-objects are created,two with the position set to ’Before’ and pointcut set to ’p1’ and ’p2’, and onewith position set to ’After’ and pointcut set to ’p3’. Finally, the parser tries tomatch any pointcut identifiers used in the attribute to a declared identifier inthe before mentioned table of pointcuts, in a way that is described below.

6.2 Weaving implementation

This section discusses the implementation of the weaving process. I start bydescribing how the different types of advice methods are implemented, and thenI discuss how the weaver determines where the advice should be executed.

6.2.1 Implementation of the advice methods

The different types of advice methods were defined in the previous chapter.I will now discuss how advice methods in general are implemented, and thengo into detail with the specifics about how first before- and after-advice areimplemented, and then how around-advice is implemented.

As described previously, an advice methods consists of a head and a body. The

Page 65: A simple aspect-oriented language based on C#etd.dtu.dk/thesis/246031/bac09_17.pdf · Summary This report, titled "A simple aspect-oriented language based on C#" is about my work

6.2 Weaving implementation 53

head contains the positions and pointcuts of the advice method, and the bodycontains the code to be executed. The position describes where, in relation to ajoin point, the advice should be executed. Positions and pointcuts are paired, sothe programmer specifies that the advice should come for example before someset of join points, and after some other set.

The head of the advice methods are implemented as C# attributes, also knownas annotations. An attribute is specified by enclosing the name of the attributein square brackets, and placing it in front of the declaration of the entity the at-tribute should apply to — in this case, the advice method. One can declare one’sown types of attributes by creating a class that inherits from the Attribute-class. I have declared the attribute classes BeforeAttribute, AfterAttributeand AroundAttribute, which allows a programmer to specify an advice methodlike the following:

1 [ Before ( p1 ) , After ( p2 ) ]2 private void adviceMethod ( )3 {4 /* advice body */5 }

where p1 and p2 are pointcuts.

The return type of the advice methods should be void, and they should bedeclared as private. The return value from a before- or after-advice methodis of no use, since the programmer can not make a call to these methods, andthe aspect weaver will alter the return type of the around-advice, as discussedbelow. The reason they should be private is that it is illegal to make a methodcall to these methods from the rest of the program. The access specifier andreturn type is checked by the aspect weaver, and an exception is thrown if theyare not private and void, respectively.

Above, I have described how advice methods are declared by the programmer.Now, I will go into how the aspect weaver, given an advice method as theone above, can make sure that the advice body is executed at the correct joinpoints. Before- and after-advice methods are implemented almost the same way,but around-advice requires some special handling.

When the parsing is done, the weaver has a list of all join points and advicemethods. It then goes through the list of advice methods, finds the set of joinpoints that are matched by the pointcut in an advice methods head, and weavesthe advice body into the join point. Below, I will discuss in detail how the

Page 66: A simple aspect-oriented language based on C#etd.dtu.dk/thesis/246031/bac09_17.pdf · Summary This report, titled "A simple aspect-oriented language based on C#" is about my work

54 Implementation

aspect weaver deals with the different types of advice methods.

Before- and after-advice

Before- and after-advice methods are characterised by the fact that the body ofthe advice is to be executed either before or after each join point specified bya pointcut. The advice body is contained within the advice method, which isdeclared in an Aspect. The advice body is just regular C# code, and an Aspectis like a class, so the weaving can be achieved in two ways:

1. Copy the advice method to the join point’s position

2. Convert the advice method to a static method, and insert a call to thismethod from the join point

The first approach is simple. Since the program is represented as a parse tree,the advice body is a subtree of that parse tree. Therefore, this subtree can becopied from the aspect parse tree and inserted into the C# parse tree in thecorrect position in relation to the join point. If the advice method is the ’before’-type, then the subtree should be inserted in the beginning of the join pointmethod body, and if the advice method is the ’after’-type, the subtree shouldbe inserted right before each return-statement of the join point method body.Then, calls to thisJoinPoint should be mapped to the relevant information,such as the join points name or list of arguments. Since the weaver knows whichjoin point the code is inserted at, it is possible to simply exchange the calls tothisJoinPoint with instances of the needed information.

This approach has the drawback, though, that the subtree might have to becopied and inserted many times, and if the advice body is more than a few linesof code, this will result in a lot of extra code in the modified C# parse tree.Also, the weaver must make sure that there are no naming conflicts betweenvariables declared in the advice body, and variables declared in the join pointmethod body.

The other approach is to keep the advice body in the advice method, and justmake a call to this method from the join point. This involves generating anode or subtree of the parse tree representing a call to the advice method, andinserting this node in the correct location in the C# parse tree, with regardsto the join point. This requires the advice method to be static, since thejoin point can not otherwise make a call to it. Also, I noted above that advicemethods should be private, so that a programmer can not make an explicit

Page 67: A simple aspect-oriented language based on C#etd.dtu.dk/thesis/246031/bac09_17.pdf · Summary This report, titled "A simple aspect-oriented language based on C#" is about my work

6.2 Weaving implementation 55

call to an advice method. The aspect weaver needs to make the advice methodpublic so that the join point can access it, so the advice method should beconverted from private void to public static void.2.

Another thing that needs to be handled, is the information required by calls tothisJoinPoint. As described in the previous chapter, thisJoinPoint gives theadvice method access to some information about the join point it is executing at.If the advice body is kept in a method in the Aspect-class, then the informationrequired needs to be passed along as arguments, when the method is called.Since the method is called from the join point, and the information required isregarding the join point, the weaver is able to build the list of arguments andpass it along with the method call.

The method I have chosen to implement is the second approach, mainly becauseI think it is the easiest approach to implement. It only involves changing thevisibility of the method, making it static, building an argument list and creatinga message call node. The other approach would have to analyse the advicebody and the join point body and figure out if any variables share identifier. Italso raises some issues that would need more deliberation, such as what shouldhappen if there is a return-statement in the advice body — should this returnstatement also be inserted at the join point? If so, what should it return, if thereturn type of the join point is not void?

Because of this, I think it is simpler, and makes more sense to implement thesecond approach. This way, the before- and after-advice bodies will just be codeexecuted at a join point, with no control over the execution of the join point -this functionality is reserved for around-advice.

The weaving process for before- and after-advice type methods is shown in figure6.3. Each box is labelled with a small number, which I will use to explain whathappens at each step. The process starts with the advice method representedas a subtree of the advice parse tree.

1. First, a search through the subtree is performed to find all calls to membersof thisJoinPoint

2. Each time such a call is found, a (key,value)-pair is added to a map, wherethe key is a variable or an array declaration, and the value is the valuerepresented by that identifier. For example, the key string s1 could mapto thisJoinPoint.MethodName, while Object[] s2 could map tothisJoinPoint.MethodArguments

2This introduces a problem where a programmer can actually call the advice methodanyway, which I will discuss below

Page 68: A simple aspect-oriented language based on C#etd.dtu.dk/thesis/246031/bac09_17.pdf · Summary This report, titled "A simple aspect-oriented language based on C#" is about my work

56 Implementation

B/Aadvice a()Pointcut: p

Find all calls tomembers of

thisJoinPoint (tJP)

HashMap

{tJP.MethodName string s1tJP.MethodArgumentsObject [ ] s2}

Modify advice Method(change visibility to

public static, add arguments and

switch calls to tJP withargument)

a() TypeBefore AfterInsert method call

to a() as first child nodeof m()

Return typeof m()

void

¬void

Insert call to a() before all return-

statements, and aslast child node

of m()

Insert call to a()before all return-

statements ofjoin point m()

1

23

5 4

7

6

8

For each join point m() matched by pointcut P

Figure 6.3: The process of weaving before- and after-advice

3. Based on this map, the advice method is modified. Each entry in thehashmap translates to an argument of the advice method, and the corre-sponding call to thisJoinPoint should be replaced with this argumentidentifier, so from the above map, the advice signature would be pri-vate void a(string s1, Object[] s2), and references to thisJoin-Point.MethodName and thisJoinPoint.MethodArguments would be re-placed with s1 and s2, respectively. Also, the visibility of the method ischanged from private to public static, while keeping its void returntype.

4. For each join point m() in the C# program matched by the pointcut givenin the advice methods head, the following is done:

5. If the position of the advice method is ’before’, a call to the advice method

Page 69: A simple aspect-oriented language based on C#etd.dtu.dk/thesis/246031/bac09_17.pdf · Summary This report, titled "A simple aspect-oriented language based on C#" is about my work

6.2 Weaving implementation 57

is inserted at the top of m()

6. Else, the position of the advice method is ’after’, and the return type ofm() is determined

7. If the return type is void, a call to the advice method should be placedbefore every return-statement in m() and at the very end of m()’s body

8. Else, if the return type is different from void, a call to the advice methodshould just be placed before every return-statement

Let us see how this looks by looking at our running example. For loggingpurposes, we want to output some information to the console each time a file isaccessed, whether it is for writing or reading. Therefore, we have the followingadvice method in our LoggingAspect aspect:

1 [ Before ( " example . File .* " ) ]2 public void LogFi leAccess ( ) {3 Object [ ] arguments = th i sJo inPo in t . getMethodArguments ( ) ;4 Console . WriteLine ( th i s Jo inPo in t . getMethodName ( ) + " () accessed ...

with arguments :" ) ;5 foreach ( Object o in arguments )6 Console . WriteLine ( " " + o . ToString ( ) ) ;7 }

This advice is meant to be executed each time a method in the File-class iscalled. It fetches the name of the method, as well as the arguments passed to themethod, and outputs both. One of the intercepted join points is the followingmethod from the File-class:

1 public void WriteToFile ( string data , User user ) {2 FileData += data ;3 }

During the weaving process, all references to members of thisJoinPoint arereplaced with an identifier, which is added to the argument list. After theweaving process, the advice method therefore looks like this:

Page 70: A simple aspect-oriented language based on C#etd.dtu.dk/thesis/246031/bac09_17.pdf · Summary This report, titled "A simple aspect-oriented language based on C#" is about my work

58 Implementation

1 static public void LogFi leAccess ( Object [ ] s1 , string s2 ) {2 Object [ ] arguments = s1 ;3 Console . WriteLine ( s2+" () accessed with arguments :" ) ;4 foreach ( Object o in arguments ) {5 Console . WriteLine ( " "+o . ToString ( ) ) ;6 }

Now, a call to this method is inserted at the top of every matching join point,which is every method in the File-class. After the weaving, the WriteToFile-method from before looks like this:

1 public void WriteToFile ( string data , User user ) {2 LoggingAspect . LogFi leAccess ( new Object [ ] {data , user } , "...

WriteToFile " ) ;3 FileData += data ;4 }

We see that the weaver creates the argument list simply by inserting the relevantinformation into the method call.

A problem with the chosen approach, is that the weaver has to convert the advicemethod to public static. The reason advice methods should be declaredprivate in the first place, is that calls to these methods should always be madeby the aspect weaver, and not the programmer. The aspect weaver is able toconvert the visibility of the advice method from private to public, and thisallows a programmer, who is familiar with the implementation, to circumventthe restriction on calls to advice methods. If he knows that the visibility ofadvice methods are changed to public, and that they are made static, he cansimply make calls to them anyway, and when the aspect weaver has modifiedthe advice method, these method calls will be legal.

There are two solutions to this problem. First, it can be solved through ob-scurity, by simply having the aspect weaver rename the advice method to somerandom name. This way, if a programmer tries to make a call to the advicemethod, it will not exist and the compiler will report an error. The other wayis to analyse the source code, and make sure that there are no explicit callsto advice methods, and return an error if there is. I have not implementedeither approach, so at the time of writing, it is possible to make a call to advicemethods, even though it is not allowed.

Page 71: A simple aspect-oriented language based on C#etd.dtu.dk/thesis/246031/bac09_17.pdf · Summary This report, titled "A simple aspect-oriented language based on C#" is about my work

6.2 Weaving implementation 59

Around-advice

Around-advice differs from before- and after-advice in the way that some of thebody of the advice method is executed before the join point, and some of thebody is executed after. Also, the advice method has some control over the joinpoint, in the way that it can prevent the join point from executing at all, or itcan be executed multiple times.

Recall from the previous chapter, that around-advice methods are written as asingle method, utilising calls to thisJoinPoint.proceed() to execute the joinpoint. To be able to do this, the location of the call to the join point must bemoved from the calling code to the advice method. This can be accomplished byhaving the original calling code call the advice method instead, and then havethe advice method call the join point whenever a thisJoinPoint.proceed()-statement is encountered.

To describe how this is done, let us consider the following piece of code fromthe running example:

1 class F i l e {2 . . .3 public void WriteToFile ( string data , User user ) {4 FileData += data ;5 }6 }7

8 class Program {9 . . .

10 static void Main( string [ ] a rgs ) {11 . . .12 WriteToFile ( " somedata " , user ) ;13 . . .14 }15 }16

17 [ Aspect ]18 class Secur i tyAspect {19 . . .20 [ Around ( " File . WriteToFile " ) ]21 private void checkWriteFi l eAccess ( )22 {23 if ( ( RequiredWriteAccessLevel & user . UserAccessLeve l ) != 0)24 thisJoinMethod . proceed ( ) ;25 else26 Console . WriteLine ( user . UserName + " lacks access to write ...

to file " ) ;27 }28 }

Here, we have a join point, WriteToFile, a call to this join point in the Main-

Page 72: A simple aspect-oriented language based on C#etd.dtu.dk/thesis/246031/bac09_17.pdf · Summary This report, titled "A simple aspect-oriented language based on C#" is about my work

60 Implementation

method and an around-advice method that encapsulates the join point. First,the call to the join point from the Main-method should be changed to a callto the advice method. Second, thisJoinMethod.proceed() should be replacedwith a call to the join point. This way, the advice method would be wrappedaround the join point, controlling the execution.

First, for the advice method to be able to call the join point, the advice methodneeds to be moved to the File-class. This is accomplished by making a copyof the subtree representing the advice method, and inserting it as a child of theFile-class. A copy of the advice method should be made for each matchingjoin point, and inserted as a method of that join points class. Next, we need tomake the Main-method call the advice method instead of the join point. Thiscan either be achieved by altering the call in the main method, or by renamingthe advice method to the name of the join point, and renaming the join point tosome new unique name. The second approach is the easiest way, since otherwisethe weaver would have to look through the entire parse tree, looking for calls tothe join point, and changing them all.

If the advice method is renamed to the name of the join point, it also needs totake over the join points visibility, return type and argument list. The argumentlist can be passed along to the join point with the proceed-statement.

The process of weaving around-advice is illustrated in figure 6.4.

6.2.2 thisJoinPoint

As described in the previous chapter, I use an object called thisJoinPoint toexpose information about a join point to the advice method. Chapter 5 men-tioned a list of information that would be useful in this regard. Unfortunately,I havn’t been able to implement them all, but here is the list of methods thatare available:

• Before- and after-advice

– thisJoinPoint.MethodName - The name of the join point, given asa string

– thisJoinPoint.MethodArguments - An array of the arguments passedto this join point, given as an array of the type Object

• Around-advice

– thisJoinPoint.MethodName

Page 73: A simple aspect-oriented language based on C#etd.dtu.dk/thesis/246031/bac09_17.pdf · Summary This report, titled "A simple aspect-oriented language based on C#" is about my work

6.2 Weaving implementation 61

For each join point m() matched by pointcut P

around-advice a()Pointcut: P

Make a copy ofa() and rename to m(),setting this method's

argument list, return typeand visibility to that of

the original m()

Rename original m() to m'(), where m'() is a unique name

Replace all calls tothisJoinPoint.Proceed()

with calls to m'(),passing the argument

list along. Also change all other calls to thisJoinPoint

with correct information

Add the new m() as a sibling to m'()

Figure 6.4: The process of weaving around-advice

– thisJoinPoint.Proceed() - Tells the weaver that the join pointshould be executed here

The programmer uses thisJoinPoint simply by making a reference to thesemembers. When the aspect weaver is processing an advice method, it scans itfor references to thisJoinPoint, and replaces these references with a relevantnew subtree in the parse tree.

6.2.3 Matching join points to pointcuts

Above, I have described how the aspect weaver weaves the different types ofadvice methods. In this section I discuss how the weaver finds out where theadvice methods should be executed, based on the pointcuts defined in the headof the advice method, and the set of join points in the program.

Before the weaving can be done, the aspect weaver need to find out, for eachadvice method, which join points are matched by the pointcut. To be able to

Page 74: A simple aspect-oriented language based on C#etd.dtu.dk/thesis/246031/bac09_17.pdf · Summary This report, titled "A simple aspect-oriented language based on C#" is about my work

62 Implementation

specify a set of join points in an easy way, a pointcut consists of three parts,of which two are optional: a namespace, a classname and the name of the joinpoint. The namespace and classname are optional, but if they are present, theyare separated by a dot. If one part is present, it is interpreted as the joinpoint name; if two parts are present, they are interpreted as classname andjoin point. If a namespace is missing, the namespace in which the pointcut isdeclared is used, and if a classname is missing, it is interpreted as all classesin that namespace. As such, def.ghi refers to join point ghi in class def inthe same namespace as the Aspect in which this pointcut is declared, whileabc.def.ghi refers to join point ghi in class def declared in namespace abc.Each of these can also be represented as a wildcard, denoted by the symbol *.As such, abc.def.* refers to all join points in the class named def, defined innamespace abc. Note that as a consequence, *.ghi and ghi refer to the sameset of join points, namely the join points named ghi in any class declared in thesame namespace as the pointcut.

The pointcut is parsed by the following regular expression:

^((([a-zA-Z_]\w*)|\*)\.)?((([a-zA-Z_]\w*)|\*)\.)?(([a-zA-Z_]\w*)|\*)$

This follows the syntax of C# regular expressions, where [a-zA-Z ] denotes allletters, lowercase and uppercase, as well as the symbol ’ ’. \w denotes all upper-and lowercase letters, and digits. ? means that a group is optional, * meansthat a group can occur 0 or more times, — means the union of two groups,paranthesis are used for grouping, and \* and \. represent the symbols ’*’ and’.’, respectively. Theˆand $ characters specify that the regular expression mustmatch the whole parsed string, instead of just trying to find a substring thatmatches.

As such, the regular expression first looks for an optional group consisting ofeither the symbol ’*’, or a string of characters, digits and the symbol ’ ’, startingwith a character or ’ ’ and ending with a ’.’. Then comes a similar group, whichis also optional, and finally comes a similar group, except this one should notend with a ’.’. This last group is mandatory.

The above regular expression does not implement the boolean operators avail-able on pointcut designators, as I described in the previous chapter. I havedecided to not implement these yet. One can make a conjunction of pointcutsby giving an advice method several positions, for example [Before(p1), Be-fore(p2)]. This advice method header states that the advice method shouldcome before the join points matched by the conjunction of the two pointcutdesignators, p1 and p2.

Page 75: A simple aspect-oriented language based on C#etd.dtu.dk/thesis/246031/bac09_17.pdf · Summary This report, titled "A simple aspect-oriented language based on C#" is about my work

6.2 Weaving implementation 63

To implement the logical operators, as described in the previous chapter, theregular expression above should be extended, and the PointCut-class, which isresponsible for parsing pointcut designators using the regular expression, shouldbe extended to support the logical operations.

When a pointcut is declared, it it parsed by this regular expression, and thenamespace, classname and join point name is determined. This enables theaspect weaver to check if a join point is matched by a pointcut. For each advicemethod, it checks all join points against the pointcut using the following formula:

Definition 6.1match =

JoinPoint.Type = Method ∧(PointCut.NameSpace = "*"∨ PointCut.NameSpace = JoinPoint.NameSpace) ∧

(PointCut.Class = "*" ∨ PointCut.Class = JoinPoint.Class) ∧(PointCut.JP = "*" ∨ PointCut.JP = JoinPoint.Name)

This checks that the join point is a method (which is the only implemented joinpoint type at the moment), and that it is matched by the pointcut.

6.2.4 Matching pointcut designators to advice methods

As described previously, the head of an advice method consists of two compo-nents: the position(s) of the advice method, and the pointcut associated witheach position. For example, an advice method can have the head

[Before(p1), After(p2)]

where p1 and p2 are pointcut designators. These designators may either beliterals or identifiers. For example, the previous header might be written as thefollowing, if p1 should match all join points with the name ”m” and p2 shouldmatch all join points with the name ”n”:

PointCut p1 = "m";[Before(p1), After("n")]

Here, p1 is an identifier, and ”n” is a literal.

When parsing, the weaver builds a list of all advice methods, and all pointcutdesignators declared as variables, like p1 above, and it needs to match those

Page 76: A simple aspect-oriented language based on C#etd.dtu.dk/thesis/246031/bac09_17.pdf · Summary This report, titled "A simple aspect-oriented language based on C#" is about my work

64 Implementation

identifiers to the appropriate advice methods, so the advice method has the valueof the pointcut designator instead of an identifier. When the parser discoversan advice method, it examines the head for any pointcut identifiers. If there areany of these, it looks in the list of pointcut variables for a match. If a matchis found, it replaces the identifier with the value of the variable. This is notguaranteed to switch all pointcut identifiers with their values, though. Not allpointcuts may have been discovered when an advice method is found, so whenthe parsing is done, the aspect weaver needs to go over all advice methods againand check if there are any pointcut identifiers left in the heads. If this is thecase, it must find the value of the pointcut, and replace the identifier.

This way, all pointcut designators in the advice methods head are specified asliterals. Therefore, it is easy to find out if an advice method should be wovenin at a specific join point, using the process described in the previous section.

Scope

When doing the matching process described above, the weaver needs to takethe scope of the pointcut declarations into account. Pointcuts declared in thescope of a method makes little sense, since a pointcut is only used in the head ofadvice methods, which can not be declared inside another method, so pointcutsdeclared inside a method are simply ignored. Pointcuts declared in anotheraspect should not be used by an advice method. This can be achieved bystoring the scope of the pointcut designator, when its declaration is encounteredby the parser, and then, when the matching described in the previous section isdone, check that the location of the advice method and the scope of the pointcutdeclaration match.

When a pointcut is encountered by the parser, it is put in a table of pointcuts,as described previously, where the key in the (key,value)-pair is the pointcutidentifier. To incorporate the scope of the pointcut into this, and at the sametime enable pointcuts with the same name but declared in different aspects tobe stored in the table, the key is composed of namespace.aspect.pointcut.For example, if a pointcut p1 is declared in the aspect SecurityAspect in thenamespace AspectNamespace, then it would be stored in the table asAspectNamespace.SecurityAspect.p1.

Another approach, that would work as well, is for each aspect to have its owntable of pointcuts. This would achieve the same thing, but might require a bitmore administration and work when looking for a specific pointcut.

Page 77: A simple aspect-oriented language based on C#etd.dtu.dk/thesis/246031/bac09_17.pdf · Summary This report, titled "A simple aspect-oriented language based on C#" is about my work

6.3 Chapter Summary 65

6.3 Chapter Summary

In this chapter, I have described how I have implemented the most importantparts of the aspect weaver. In the previous chapter, I gave a description ofthe design an overall architecture of the solution, and in this chapter, I havein more detail described how the different components of this architecture hasbeen implemented.

I have discussed parser generators, and discussed why Coco/R, the parser gen-erator I have chosen, fits this project. The job of the parser generator is tomake sure that the input is syntactically valid, and to generate a parse tree anda symbol table. I have further discussed the structure of this parse tree and howit is implemented and generated, as well as the symbol table, which consists ofthree lists: one for join points, one for pointcuts and one for advice methods.

The main focus of this chapter has been to describe the implementation of theweaving-part of the aspect weaver. I have described how the different typesof advice method, ”before”, ”after” and ”around”, have been implemented bymodifying the parse trees, so that method calls to ”before” and ”after”-advicemethods are inserted at the correct places before and after a join point, andhow ”around”-advice methods take the place of the original join point, whichgives them the ability to control the execution of the join point.

Page 78: A simple aspect-oriented language based on C#etd.dtu.dk/thesis/246031/bac09_17.pdf · Summary This report, titled "A simple aspect-oriented language based on C#" is about my work

66 Implementation

Page 79: A simple aspect-oriented language based on C#etd.dtu.dk/thesis/246031/bac09_17.pdf · Summary This report, titled "A simple aspect-oriented language based on C#" is about my work

Chapter 7

Test

This chapter describes the various methods of testing that have been done todiscover and fix any bugs and errors that have been introduced during theimplementation. As Dijkstra said in Dijkstra (1972):

Program testing can be used to show the presence of bugs, but neverto show their absence!

The testing described in this chapter tries to improve the confidence that thereare no serious bugs in the implementation, but it can not be taken as a proofthat the program is correct.

To assert that the program is correct, I could have made various proof as to thecorrectness of the algorithms used and tried to prove that, given a certain classof input, correct output would be given by the program. The aspect weaver Ihave created, though, builds on so many well known algorithms, datastructuresand tools such as trees, breadth-first search, regular expressions, scanners andparsers, which have been proven correct again and again, that I have foundit unnecessary to spend time on making formal proofs. As Knuth once said(Knuth)

Beware of bugs in the above code; I have only proved it correct, not

Page 80: A simple aspect-oriented language based on C#etd.dtu.dk/thesis/246031/bac09_17.pdf · Summary This report, titled "A simple aspect-oriented language based on C#" is about my work

68 Test

tried it.

The above quote, although joking in tone, implies that proof of correctness isonly one part of verifying a program. One must also make tests to assert thatthe proven algorithm is implemented correctly before one can have faith in theprogram.

The testing has been following the development process on a rather ad hocbasis, where a feature has been tested after having been implemented, andvarious random tests have been done to see if any situations cause the programto crash or give incorrect output. Near the end, I have attempted a morestructured approach to testing with some automated test cases, where I definethe expected output of a test case, and then run the program and compare theexpected with the actual output.

In the next few sections, I will describe how the testing has been done, and giveexamples of the types of bugs that have been discovered and fixed due to thistesting. I will also give a list of bugs and issues that have been discovered dueto testing, but not yet fixed, as well as a discussion on how these issues mightbe fixed later.

7.1 Ad hoc testing

The most informal and unstructured test method that has been used in thisproject is called ad hoc testing. My definition of ad hoc testing is a form oftesting performed without planning and documentation, with the purpose oftesting that some newly implemented functionality works as designed and donot break any existing code, by compiling and running the program with someinput meant to expose any bugs in the new code. This type of testing is agile,since it does not require much forethought, but can be used to quickly test smallpieces of functionality soon after implementing them. Ad hoc testing is also asort of explorative test method, where one test might lead to another test, ifthe first test reveals any deeper issues than what was initially tested for.

Ad hoc testing has been used extensively throughout the development process.This type of testing is characterised by the speed with which such testing canbe performed, so it is ideal for a quick test of newly written code to see if thecode performs as expected, without crashing or doing anything unexpected. Thetesting process can be described as follows:

Page 81: A simple aspect-oriented language based on C#etd.dtu.dk/thesis/246031/bac09_17.pdf · Summary This report, titled "A simple aspect-oriented language based on C#" is about my work

7.2 Automated testing 69

1. First, a piece of code is written, implementing some needed functionality.This can, for example, be a member of thisJoinPoint

2. The code is compiled to check for any syntax errors, and run on an oldinput to verify that it does not crash or break anything at first glance

3. The old input code is modified to use the new functionality, for examplea call to the new thisJoinPoint member

4. The new input code is fed through the aspect weaver, and the output codeis analysed to see if it looks like expected

5. Optionally, the output code is compiled, verifying that the program gen-erated actually compiles, runs and gives the expected output

This testing process can be completed in just a few minutes, and catches anyimmediate bugs such as uncaught exceptions, crashes and obviously wrong be-haviour.

7.2 Automated testing

In an attempt to do more planned and structured tests, to consistently checkthat new versions of the aspect weaver still produces correct output when givena set of input files, I have created a series of test cases, with the intention to setup an automated test suite.

The purpose of this test suite is to provide an easy method of testing that anew version of the aspect weaver still satisfies the requirements and produces thecorrect output. The idea is that, based on the design description of the weaver, itis possible to write small programs in C# and aspect code that uses the weavingprocess to give some output, and then predict what this output will be. Thetest case then consists of a small program and a file with the predicted output.When the test is performed, the program is given to the aspect weaver, whichgenerates an altered (woven) program which is compiled by a C# compiler.The compiled program is run, resulting in some output which is compared tothe previously mentioned predicted output. If the two files differ, there is aproblem with the aspect weaver, and the test fails. If, on the other hand, thetwo files are identical, then the weaver still produces the correct output giventhis input, and the test succeeds. Given a large enough number of test casestesting different functionalities, both individually and combined, one can makesure that changes done to the aspect weaver result in a program that is stillbelieved to be correct.

Page 82: A simple aspect-oriented language based on C#etd.dtu.dk/thesis/246031/bac09_17.pdf · Summary This report, titled "A simple aspect-oriented language based on C#" is about my work

70 Test

The automated tests are implemented using Microsoft Visual Studio’s unit testcapabilities. Each test case is implemented as two input files, one for the C#code and one for the aspect code, as well as a predicted output file. A testscript is written, which runs the aspect weaver as a new process, giving it thetwo source files as input. When this is done, it takes the output files, runs aC# compiler with these files as well as the aspect framework as input. Thisgenerates an executable, which is started in a new process by the test method,generating some output, which is directed to a file. Finally, the generated fileis compared with the predicted output, and the test method declares the test asuccess or failure, depending on whether the two files match.

7.3 Known issues

This section will describe some of the issues and defects that I have discoveredwith the current implementation, as well as discuss how these issues could besolved in the future.

When renaming methods, the aspect weaver does not check if amethod with the new name already exists in that context

Sometimes, the aspect weaver needs to rename a method. For example, whenan around-advice method is processed, the advice method is renamed to thename of the join point, and the join point is given a new name. With thecurrent implementation, the new name is simply the old name, with the string” aroundadvice” appended. Though it is unlikely that a programmer would,for example, name one method ”m()” and another method in the same class”m aroundadvice()”, the aspect weaver needs to make sure that a collision neverhappens. Fortunately, since there is an almost infite amount of method namesavailable, the aspect weaver will always be able to pick a new name for the joinpoint, that won’t collide with an existing method. The best approach for pickinga new name is to generate a random name of some fixed length and check ifa method with that name already exist in this context. If so, generate a newrandom name. If the random name is of sufficient length, say 6-8 characters, thechance of picking an already existing name is very small given that the amountof methods in a class is usually much lower than the amount of method namesof length 6 one can generate.

Page 83: A simple aspect-oriented language based on C#etd.dtu.dk/thesis/246031/bac09_17.pdf · Summary This report, titled "A simple aspect-oriented language based on C#" is about my work

7.3 Known issues 71

A programmer can make calls to advice methods, even though he isnot meant to

This issue has been described previously, in Chapter 6. An advice method isrequired to be declared private, but the aspect weaver need to make before-and after-advice methods public static. This means, that a programmer canmake a call to a private advice method that he should not have access to,but when the program is compiled, the method is made public and the codecompiles without warnings.

This problem can be solved by analysing the C# code, checking for calls to anyadvice methods before the weaving is done. It is difficult to do while parsing,because if a method call is encountered, the parser might not yet know if themethod being called is an advice method, since it might not have been parsedyet. A solution to this is to parse the aspect code before the C# code, butrequiring that the aspect code is parsed before the C# code is inflexible andmight lead to problems later. After parsing, however, the aspect weaver has alist of all advice methods, so it can search through the C# parse tree and lookfor calls to any of these.

Another approach, that might be simpler to implement, is to simply renamethe advice method to a random name when changing the visibility. Since theadvice method should not be called from anywhere before the weaving process,this should not result in any problems for a legal input program. Changingthe name should be simple, since it is just specified one place in the parse treeas a string value. The weaver must, however, check that there is no existingadvice method in that context with the same name as the newly generated, inthe unlikely event that a conflict happens.

The aspect weaver only accepts one C# source file and one aspectsource file

At the moment, the aspect weaver takes as input one source file for the C#code, and one source file for the aspect code. Ideally, it should be possible togive any number of source files as input. This can be accomplished by creatinga layer in front of the scanner, which accepts multiple source files and gathersthem in one big source file for the C# code, and one big source file for the aspectcode.

Page 84: A simple aspect-oriented language based on C#etd.dtu.dk/thesis/246031/bac09_17.pdf · Summary This report, titled "A simple aspect-oriented language based on C#" is about my work

72 Test

The weaver does not check for unallowed behaviour

The programmer is able to do a couple of things that are not allowed. Thesethings need to be checked, and if discovered, an error should be reported. Forexample, one can instantiate or extend an aspect. Instantiation makes nosense, since it is not an object, and inheriting from aspects is not designed norimplemented.

Page 85: A simple aspect-oriented language based on C#etd.dtu.dk/thesis/246031/bac09_17.pdf · Summary This report, titled "A simple aspect-oriented language based on C#" is about my work

Chapter 8

Future work

In this chapter, I discuss some of the things that would be interesting to addor do differently, if I were to continue working on this project. I think I havecreated a good first version of an aspect-oriented extension of C#, but there is,of course, always room for improvement and new features.

I cover a list of other things that can be implemented and give a descriptionon how this could be done, and I discuss how I could have done a few thingsdifferently, and what that would have achieved.

8.1 Implement the rest of the C# 3.0 specifica-tion

Right now, only a subset of the C# 3.0 language is supported by my aspectweaver. Some of the unsupported language features are mentioned in Chapter2, but a number of other things are missing from the implementation as well.Not all of these things are documented, so this might lead to some issues if onetries to use them when creating an aspect-oriented program.

The main reason that things from the C# specification is missing from the

Page 86: A simple aspect-oriented language based on C#etd.dtu.dk/thesis/246031/bac09_17.pdf · Summary This report, titled "A simple aspect-oriented language based on C#" is about my work

74 Future work

implementation is, that to include these things, it is necessary to add semanticactions to the C# grammar to include them as nodes and subtrees in the parsetree, and then extend the parse tree implementation so it is able to convert thesesubtrees back to C# code. I have prioritised the most useful functionality fromthe C# language, such as classes, methods, expressions, statements, loops andso on, since they are necessary to create meaningful programs. I have, however,prioritized the aspect language over the C# implementation, which is the reasona list of things are not implemented.

8.2 More aspect-oriented functionalities

In Chapter 2, I discussed some of the AOP concepts that I would not have timeto look into during this project. Here, I will discuss these concepts, and explainhow they might be added to the current implementation.

8.2.1 Larger set of join points

In the current implementation, the set of join points that are considered by theaspect weaver is limited to the set of methods. This was done to decrease theneeded complexity of the pointcut model, since a lot of simplicity can be gainedby assuming that all join points are methods.

Methods are probably the most interesting join points, and can be used tocircumvent the limited set of join points. For example, another type of joinpoint could be field access - it might be interesting to execute some advice everytime a field is read or written to. This can be accomplished with the currentimplementation, where methods are the only join points, by always accessingfields through methods, such as get/set-methods. Also, constructors might beinteresting join points, but they can also be intercepted by the current adviceimplementation - just move the body of the constructor into a method, and havethe constructor do nothing except make a call to this method.

These workarounds are, of course, not ideal since the whole purpose of aspectoriented programming is to be able to write a module without having to thinkabout how other concerns are going to work, but they illustrate the point thatthe current implementation allows a range of techniques to be used to applyadvice where needed. In the future, the design should be reworked to accommo-date a larger set of join point types, so these workaround become obsolete. This

Page 87: A simple aspect-oriented language based on C#etd.dtu.dk/thesis/246031/bac09_17.pdf · Summary This report, titled "A simple aspect-oriented language based on C#" is about my work

8.2 More aspect-oriented functionalities 75

is not trivial, though, since many assumptions are made on join points beingmethods, both in the design and in the implementation.

8.2.2 Dynamic pointcuts

As noted in Chapter 2, only static pointcuts are implemented. The differencebetween static and dynamic pointcuts are, that dynamic pointcuts are evaluatedat run-time, while static pointcuts are evaluated at weave-time. This meansthat, if a join point is matched by a static pointcut, the advice tied to thatpointcut will always be executed at the join point. A dynamic pointcut, onthe other hand, must look at the current context or state of the program todetermine if an advice method should execute at a given join point.

Dynamic pointcuts could, with some deliberation, be added to the current im-plementation. First, it would require an extension to the pointcut syntax, so aprogrammer can specify both a set of join points, and also a context in whichthese join points are matched by the pointcut. Second, changes to the weavingprocess must be made, so that advice methods only execute if the context isright.

Remember that before- and after-advice methods are implemented as calls tothe advice method inserted at the top or bottom of the join point. Dynamicpointcuts could be implemented by putting this call inside an if-statement, wherethe condition for the method call to be made is whether the specified context istrue. So given a context predicate P and an advice method advice() in aspectA, a static pointcut will result in the following code being inserted at the joinpoint:

1 A. advice ( ) ;

while a dynamic pointcut will result in the following code being inserted:

1 if (P)2 A. advice ( ) ;

Around-advice methods replace the join point, calling the renamed join pointwhen it should execute. Here, we can also use an if-statement to determine

Page 88: A simple aspect-oriented language based on C#etd.dtu.dk/thesis/246031/bac09_17.pdf · Summary This report, titled "A simple aspect-oriented language based on C#" is about my work

76 Future work

whether the advice should execute based on the current context. To control theexecution of the advice body, an if-statement should be inserted at the top of thebody, having the context predicate specified by the pointcut as the condition.If the context is false, the join point should be executed, and then the advicemethod should just return any value returned by the pointcut. For example, ifadvice() is an around-advice method and P is a context predicate, the weavershould alter the body of the method so the first lines looks like the following:

1 . . . adv ice ( ) {2 if ( !P) {3 // return thisJoinPoint . proceed () ; // if return type of join ...

point is not void4 // thisJoinPoint . proceed () ; return ; // if return type of join...

point is void5 }6 /* rest of the advice body */7 }

Some care should be taken here, in case the join point has the return type void.The aspect weaver must check for this, and insert the correct of the two optionsshown above.

This second part seems easy. The difficult part is designing an extension to thepointcut syntax that will enable the programmer to specify a context, keepingin mind that the aspect weaver must determine if this context specification isvalid.

8.2.3 Inter-type declarations

A concept from AOP that would be of interest to implement, is inter-typedeclarations. With inter-type declarations, it is possible to add new fields andmethods to a class from an aspect. This can be used for many different things,such as implementing design patterns, having a counter that counts how manytimes a method has been executed, and generally implementing concerns thatare related to an object, but cross-cut the main concern of that object.

Implementing inter-type declarations should be relatively straightforward. Theprogrammer should declare the field or method in the aspect and specify whichclass should own these declarations, and then the aspect weaver could simplymove the subtree representing the declaration from the aspect to the correctclass.

Page 89: A simple aspect-oriented language based on C#etd.dtu.dk/thesis/246031/bac09_17.pdf · Summary This report, titled "A simple aspect-oriented language based on C#" is about my work

8.3 Implement a compiler back-end 77

8.3 Implement a compiler back-end

As I have described earlier, I have implemented part of a compiler front-end, inthe form of a lexer and a parser. These read the input source code and generatea parse tree, which is passed to the weaver. When the weaver is done processingthe parse tree, it is converted back to C# code, before being passed to a C#compiler.

An obvious improvement would be to implement a compiler back-end and addit to the aspect weaver. This way, instead of having to convert the parse treeback to C# code and then pass it to a 3rd party program, the weaver couldjust send the tree to another part of the program which would compile it intobytecode. This would make for a more complete solution, that would be easierto maintain, since it would not depend on the C# compiler staying the same.It would also make the tool easier to integrate into a development environment,since it would be just like swapping one compiler for another, which manydevelopment environments support.

To do this, it would be necessary to put more work into the tree-generation.If the parse tree is to be used for code generation in another language thanthe input language, it would probably benefit from a better structure. Manycompiler designers prefer the use of abstract syntax trees over parse trees1, sincethey are less tied to the input language.

A compiler back-end not only involves code generation, which requires knowl-edge of the target architecture and language (in this case, the .NET virtualmachine and the Common Intermediate Language); it also involves analysis andoptimisation.

8.4 Use a different weaving strategy

In Kiczales et al. (2001), the team behind AspectJ mentions a series of differentweaving strategies: ”using a special pre-processor, during compilation, by a post-compile processor, at load time, as part of the virtual machine, using residualruntime instructions, or using some combination of these approaches”. Themain purpose of this section is to show that there are many different approachesto a successful AOP implementation.

1Also called concrete syntax trees

Page 90: A simple aspect-oriented language based on C#etd.dtu.dk/thesis/246031/bac09_17.pdf · Summary This report, titled "A simple aspect-oriented language based on C#" is about my work

78 Future work

8.4.1 Bytecode weaving

With a language such as C#, which is translated into bytecode before beinginterpreted/compiled to machine code, the weaving can also be done at twolevels: on the original code, or on the byte code. This would allow a programmerto write his code in any .NET language, and still be able to use this tool to weavethe normal code and the aspect code together.

To do this, the weaving process would need to be located after the compilation tobytecode had occured. This could be done by parsing the bytecode from a .NETassembly, parsing the aspect code written in a specific language, for examplethe C# aspect language I have created in this project, and then weaving thosetwo together, outputting the woven program as bytecode.

8.4.2 Deploy-time weaving

Deploy-time weaving is the approach used by the AspectJ2EE implementation(Cohen and Gil, 2004). The motivation behind deploy-time weaving is that otherweaving strategies breaks the standard object model of the original language,which might effect portability and language processing tools, such as debuggers.One can not use a standard debugger with my implementation of AOP, forexample, since the aspect weaver modifies the original program, altering linenumbers and class structure before compilation. The idea behind deploy-timeweaving is that instead of modifying the original code or the compiled binaries, adeploy-time aspect weaver ”generates new classes that inherit from, rather thanreplace, the core program files. Aspect application is carried out by subclassing,during the deployment stage, the classes that contain the business logic”(Cohenand Gil, 2004). Then, the original and generated classes are deployed side byside. This allows standard debuggers to work like normal, because the originalcode executing is still located in the original class files, which are unaltered.

Page 91: A simple aspect-oriented language based on C#etd.dtu.dk/thesis/246031/bac09_17.pdf · Summary This report, titled "A simple aspect-oriented language based on C#" is about my work

Chapter 9

Conclusion

When I began this project, I set out to create a simple implementation of anaspect-oriented programming language. Before the project began, I considereddifferent options of doing this, such as creating my own programming languagefrom scratch, or extending an existing language with aspect-oriented capabili-ties.

I decided to take an existing, widely used language and extend it, to makeit possible to employ aspect-oriented software development techniques. Thechoice landed on C#, because it is a popular, object-oriented language, and hasa strong resemblance to Java, for which there already exists an AOP extensioncalled AspectJ. I decided to be inspired by AspectJ, and create an extension toC# with some of the same features that AspectJ offers to Java programmers.

The motivation for creating an aspect-oriented programming language is thatit helps the programmer to separate cross-cutting concerns, such as logging,security, synchronisation, memory management, etc. This makes it possible toreduce tangling and scattering of code, makes it easier to encapsulate and reusecode and as a consequence, it should make programming easier.

During the analysis phase, I have identified several important concepts related toaspect-oriented programming, such as join points, pointcuts and advice. I havedesigned a language where one can declare pointcut designators, which match a

Page 92: A simple aspect-oriented language based on C#etd.dtu.dk/thesis/246031/bac09_17.pdf · Summary This report, titled "A simple aspect-oriented language based on C#" is about my work

80 Conclusion

set of join points. The set of all join points is equal to the set of methods, andone can specify a subset of this set through a pointcut designator. This is thenused to declare an advice method, which injects advice, which is a small pieceof code, in before or after the join points specified by the pointcut.

The approach I have taken to implement my aspect-oriented extension of C#is to create a preprocessor, which takes the source code for the program asinput, uses the weaving techniques I have defined to modify it, and producesC# code as output, which is then used as input by a standard C# compiler.The preprocessor is implemented as a compiler front-end, with a lexical analyserand a syntax analyser, which generates a parse tree, and then the aspect weaver,which is responsible for weaving the advice into the program. The parse tree isable to output itself as valid C# code, through a series of recursive calls, andthis output can be passed to the C# compiler.

With my implementation, I have been able to create a small example program,which shows how aspect-oriented programming can be used to separate suchcross-cutting concerns as logging and security in a very simple file system. Ihave used this program, as well as a series of dedicated test cases, to verifythat my aspect weaver produces correct output when given valid input. Eventhough I have not proved my program to be correct, I have confidence that itwill generate the correct output for a large set of valid input.

In conclusion, I have been able to design and implement a simple, yet usableaspect-oriented extension to C#. I have outlined a number of future work itemsto further enhance and develop the implementation and overcome the knownlimitations, but this first version is a good working example of an aspect-orientedextension to C#

Page 93: A simple aspect-oriented language based on C#etd.dtu.dk/thesis/246031/bac09_17.pdf · Summary This report, titled "A simple aspect-oriented language based on C#" is about my work

Appendix A

Language guide

Below is a quick introduction how to create an aspect-oriented program.

First, create two files; one for the aspect code, and one for the C# code.

In the C# code, write normal C# code for your non-crosscutting modules.

In the aspect code, you write your aspects, which are the cross-cutting concerns.

First, either the namespace used for the C# code and the aspect code shouldbe the same, or there should be an import of the aspect namespace into the C#file.

To create an aspect, create a class in the aspect code file and annotate it withthe attribute [Aspect]. All classes in the aspect code file must be annotated thisway.

An example:

1 namespace example {2 [ Aspect ]3 class SomeAspect {

Page 94: A simple aspect-oriented language based on C#etd.dtu.dk/thesis/246031/bac09_17.pdf · Summary This report, titled "A simple aspect-oriented language based on C#" is about my work

82 Language guide

4 . . .5 }6 }

Next, you create your pointcuts and advice methods.

A pointcut can be declared either using the PointCut-class, like this:

1 PointCut p1 = ’ ’∗ ’ ’ ;

Or as a const string, annotated with the [PointCut] attribute, like this:

1 [ PointCut ]2 const string p1 = "*" ;

If the first approach is used, the aspect code file can not be compiled by a C#compiler unvowen.

The value of a pointcut should follow the template:

1 [ namespace . ] [ c lassname . ] jo inpointname

Where namespace and classname is the position of the join point, and join-pointname is the name. Each can be replaced by a wildcard, ”*”, which matchesanything, and the namespace and classname can be omitted. If the namespaceis omitted, the pointcut uses the namespace where it is declared itself, and if theclassname is omitted, it implies a ”*”. The name of the join point is mandatory,but can be replaced with a wildcard.

Notice: At the moment, the namespace can not contain dots! So you can writeLogging.Logger.Log, but not Util.Logging.Logger.Log.

Finally, you delare your advice methods. You specify the head of the advicemethod using an attribute, listing pairs of positions and pointcuts. Valid posi-

Page 95: A simple aspect-oriented language based on C#etd.dtu.dk/thesis/246031/bac09_17.pdf · Summary This report, titled "A simple aspect-oriented language based on C#" is about my work

83

tions are: Before, After and Around. The pointcut can either be a pointcutdeclared earlier, or a literal. Below are examples of advice method heads:

1 [ PointCut ]2 const string p1 = " Logging . Logger . Log " ;3

4 [ Before ( p1 ) , After ( " Logging . Logger .* " ) ]5 private void AdviceMethod1 ( ) { . . . }6

7 [ Around (p1 ) ]8 private void AdviceMethod2 ( ) { . . . }

AdviceMethod1 is executed before the method Log in the Logger class, and afterevery method in the Logger class, including Log. AdviceMethod2 is executedaround the Log method in the Logger class.

Page 96: A simple aspect-oriented language based on C#etd.dtu.dk/thesis/246031/bac09_17.pdf · Summary This report, titled "A simple aspect-oriented language based on C#" is about my work

84 Language guide

Page 97: A simple aspect-oriented language based on C#etd.dtu.dk/thesis/246031/bac09_17.pdf · Summary This report, titled "A simple aspect-oriented language based on C#" is about my work

Appendix B

Source code of runningexample

Program.cs

1 using System ;2 using System . Co l l e c t i o n s . Generic ;3 using System . Linq ;4 using System . Text ;5

6 namespace example7 {8 class User9 {

10 public string UserName ;11 public int UserAccessLeve l ;12

13 public User ( string username , int ual ) {14 this . UserName = username ;15 this . UserAccessLeve l = ual ;16 }17

18 public override string ToString ( ) {19 return " User : " + UserName ;20 }21 }22

23 class F i l e24 {25 private string FileData ;26 private int RequiredReadAccessLevel ;27 private int RequiredWriteAccessLevel ;

Page 98: A simple aspect-oriented language based on C#etd.dtu.dk/thesis/246031/bac09_17.pdf · Summary This report, titled "A simple aspect-oriented language based on C#" is about my work

86 Source code of running example

28

29 public void WriteToFile ( string data , User user ) {30 FileData += data ;31 }32

33 public string ReadFromFile ( User user ) {34 return FileData ;35 }36

37 public F i l e ( string i n i t i a l f i l e , int readac l , int wr i t e a c l ) {38 FileData = i n i t i a l f i l e ;39 RequiredReadAccessLevel = readac l ;40 RequiredWriteAccessLevel = wr i t e a c l ;41 }42 }43

44 class Program45 {46 private User ac t iveUse r ;47

48 static void Main( string [ ] a rgs ) {49 F i l e f = new F i l e ( " file1data " , 1 , 2) ;50 User user1 = new User ( " John doe " , 1) ;51

52 Console . WriteLine ( " User " + user1 . UserName +53 " reads from file : " + f . ReadFromFile ( user1 ) ) ;54 f . WriteToFile ( " new data " , user1 ) ;55 Console . WriteLine ( " User " + user1 . UserName +56 " reads from file : " + f . ReadFromFile ( user1 ) ) ;57 }58 }59 }

Aspect.cs

1 using System ;2 using System . Co l l e c t i o n s . Generic ;3 using System . Text ;4 using SharpAspects ;5

6 namespace example7 {8 [ Aspect ]9 class Secur i tyAspect

10 {11 [ Around ( " example . File . WriteToFile " ) ]12 private void checkWriteFi l eAccess ( ) {13 if ( ( RequiredWriteAccessLevel & user . UserAccessLeve l ) != 0)14 th i s Jo inPo in t . proceed ( ) ;15 else16 Console . WriteLine ( user . UserName +17 " lacks access to write to file " ) ;18 }19

20 [ Around ( " example . File . ReadFromFile " ) ]21 private void checkReadFi leAccess ( ) {22 if ( ( RequiredReadAccessLevel & user . UserAccessLeve l ) != 0)23 return th i s Jo inPo in t . proceed ( ) ;24 else {25 Console . WriteLine ( user . UserName +26 " lacks access to read from file " ) ;27 return "" ;

Page 99: A simple aspect-oriented language based on C#etd.dtu.dk/thesis/246031/bac09_17.pdf · Summary This report, titled "A simple aspect-oriented language based on C#" is about my work

87

28 }29 }30

31 }32

33 [ Aspect ]34 class LoggingAspect35 {36 [ Before ( " example . File .* " ) ]37 public void LogFi leAccess ( ) {38 Object [ ] arguments = th i sJo inPo in t . getMethodArguments ( ) ;39 Console . WriteLine ( th i s Jo inPo in t . getMethodName ( ) +40 " () accessed with arguments :" ) ;41 foreach ( Object o in arguments )42 Console . WriteLine ( " " + o . ToString ( ) ) ;43 }44 }45 }

Page 100: A simple aspect-oriented language based on C#etd.dtu.dk/thesis/246031/bac09_17.pdf · Summary This report, titled "A simple aspect-oriented language based on C#" is about my work

88 Source code of running example

Page 101: A simple aspect-oriented language based on C#etd.dtu.dk/thesis/246031/bac09_17.pdf · Summary This report, titled "A simple aspect-oriented language based on C#" is about my work

Appendix C

Test cases

As described in Chapter 7, I have created a test suite, that automatically testsa new version of the aspect weaver against a series of test cases. Below are thetest cases I have implemented.

Test case 1

This is the running example, which is a simple program that uses both around-and before-advice methods. The aspect source file consists of two aspects inthe same namespace, and the C# source file consists of three classes in thesame namespace. The two around-advice methods, checkWriteFileAccess andcheckReadFileAccess in the aspect SecurityAspect are supposed to matchthe methods WriteToFile and ReadFromFile, respectively, in the File-class.The before-advice method, LogFileAccess, is supposed to be called before everymethod in the File-class.

This test case testes a combination of before- and after-advice methods, pointcutwildcards and multiple classes where only method in one class is supposed to bematched by pointcuts. The source code being tested can be seen in AppendixB.

Page 102: A simple aspect-oriented language based on C#etd.dtu.dk/thesis/246031/bac09_17.pdf · Summary This report, titled "A simple aspect-oriented language based on C#" is about my work

90 Test cases

Test case 2

This test case tests the before-advice. The source code for the aspect is

1 using System ;2 using System . Text ;3 using SharpAspects ;4

5 namespace Test26 {7 [ Aspect ]8 class Aspect9 {

10 [ Before ( " Test2 . Program . MethodA " ) ]11 public void BeforeAdvice ( )12 {13 Console . WriteLine ( " Before method " + th i sJo inPo in t . getMethodName...

( ) ) ;14 }15 }16 }

and the C# code is

1 using System ;2 using System . Text ;3

4 namespace Test25 {6 class Program7 {8 static void Main( string [ ] a rgs )9 {

10 Program p = new Program ( ) ;11 p . MethodA( ) ;12 p . MethodB ( ) ;13 }14 public void MethodA( )15 {16 Console . WriteLine ( " In Method A" ) ;17 }18 public void MethodB ( )19 {20 Console . WriteLine ( " In Method B" ) ;21 }22 }23 }

The expected output is

Before method MethodAIn Method AIn Method B

Page 103: A simple aspect-oriented language based on C#etd.dtu.dk/thesis/246031/bac09_17.pdf · Summary This report, titled "A simple aspect-oriented language based on C#" is about my work

91

Test case 3

This test case tests the before-advice with a wildcard in the pointcut designator.The source code for the aspect is

1 using System ;2 using System . Text ;3 using SharpAspects ;4

5 namespace Test36 {7 [ Aspect ]8 class Aspect9 {

10 [ Before ( " Test3 . Program .* " ) ]11 public void BeforeAdvice ( )12 {13 Console . WriteLine ( " Before method " + th i sJo inPo in t . getMethodName...

( ) ) ;14 }15 }16 }

and the C# code is1 using System ;2 using System . Text ;3

4 namespace Test35 {6 class Program7 {8 static void Main( string [ ] a rgs )9 {

10 Program p = new Program ( ) ;11 p . MethodA( ) ;12 p . MethodB ( ) ;13 }14 public void MethodA( )15 {16 Console . WriteLine ( " In Method A" ) ;17 }18 public void MethodB ( )19 {20 Console . WriteLine ( " In Method B" ) ;21 }22 }23 }

The expected output is

Before method MainBefore method MethodAIn Method ABefore method MethodBIn Method B

Page 104: A simple aspect-oriented language based on C#etd.dtu.dk/thesis/246031/bac09_17.pdf · Summary This report, titled "A simple aspect-oriented language based on C#" is about my work

92 Test cases

Test case 4

This test case tests the after-advice with a wildcard in the pointcut designator.The source code for the aspect is

1 using System ;2 using System . Text ;3 using SharpAspects ;4

5 namespace Test46 {7 [ Aspect ]8 class Aspect9 {

10 [ After ( " Test4 . Program .* " ) ]11 public void AfterAdvice ( )12 {13 Console . WriteLine ( " After method " + th i sJo inPo in t . getMethodName...

( ) ) ;14 }15 }16 }

and the C# code is1 using System ;2 using System . Text ;3

4 namespace Test45 {6 class Program7 {8 static void Main( string [ ] a rgs )9 {

10 Program p = new Program ( ) ;11 p . MethodA( ) ;12 p . MethodB ( ) ;13 }14 public void MethodA( )15 {16 Console . WriteLine ( " In Method A" ) ;17 }18 public void MethodB ( )19 {20 Console . WriteLine ( " In Method B" ) ;21 }22 }23 }

The expected output is

In Method AAfter method MethodAIn Method BAfter method MethodBAfter method Main

Page 105: A simple aspect-oriented language based on C#etd.dtu.dk/thesis/246031/bac09_17.pdf · Summary This report, titled "A simple aspect-oriented language based on C#" is about my work

93

Test case 5

This test case tests the around-advice with a wildcard in the pointcut designator.The source code for the aspect is

1 using System ;2 using System . Text ;3 using SharpAspects ;4

5 namespace Test56 {7 [ Aspect ]8 class Aspect9 {

10 [ Around ( " Test5 . Program .* " ) ]11 public void AroundAdvice ( )12 {13 Console . WriteLine ( " Before method " + th i sJo inPo in t . getMethodName...

( ) ) ;14 th i s Jo inPo in t . proceed ( ) ;15 Console . WriteLine ( " After method " + th i sJo inPo in t . getMethodName...

( ) ) ;16 }17 }18 }

and the C# code is1 using System ;2 using System . Text ;3

4 namespace Test55 {6 class Program7 {8 static void Main( string [ ] a rgs )9 {

10 Program p = new Program ( ) ;11 p . MethodA( ) ;12 p . MethodB ( ) ;13 }14 public void MethodA( )15 {16 Console . WriteLine ( " In Method A" ) ;17 }18 public void MethodB ( )19 {20 Console . WriteLine ( " In Method B" ) ;21 }22 }23 }

The expected output is

Before method MainBefore method MethodAIn Method A

Page 106: A simple aspect-oriented language based on C#etd.dtu.dk/thesis/246031/bac09_17.pdf · Summary This report, titled "A simple aspect-oriented language based on C#" is about my work

94 Test cases

After method MethodABefore method MethodBIn Method BAfter method MethodBAfter method Main

Page 107: A simple aspect-oriented language based on C#etd.dtu.dk/thesis/246031/bac09_17.pdf · Summary This report, titled "A simple aspect-oriented language based on C#" is about my work

Bibliography

Ajdt: Aspectj development tools, 2009. URL http://eclipse.org/ajdt/. [On-line: accessed 24-June-2009].

Alfred V. Aho, Jeffrey D. Ullman, Monica S. Lam, and Ravi Sethi. Compilers:Principles, Techniques, and Tools. Addison-Wesley, 2nd edition, 2006.

ANTLR. Antlr, 2009. URL http://www.antlr.org/. [Online: accessed on21-June-2009].

AspectJ. aspectj, 2009. URL http://eclipse.org/aspectj/. [Online: ac-cessed 24-June-2009].

Siobhan Clarke and Elisa Baniassad. Aspect-Oriented Analysis and Design: TheTheme Approach. Addison-Wesley, 2005.

Tal Cohen and Joseph (Yossi) Gil. Aspectj2ee = aop + j2ee: Towards an aspectbased, programmable and extensible middleware framework. In Proc. ECOOP’04, volume 3086 of LNCS, pages 14–18. Springer-Verlag, 2004.

Edsger W. Dijkstra. Notes on structured programming. Structured program-ming, pages 1–82, 1972.

Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides. Design Pat-terns: Elements of Reusable Object-Oriented Software. Addison-Wesley, 1994.

John E. Hopcroft, Rareev Motwani, and Jeffrey D. Ullman. Introduction to Au-tomata Theory, Languages, and Computation. Addison-Wesley, 3rd edition,2007.

Jim Hugunin. Re: Source code weaving vs byte code weav-ing, 2003. URL http://osdir.com/ml/programming.aspect.general/2003-11/msg00054.html. [Online message board: accessed 24-June 2009].

Page 108: A simple aspect-oriented language based on C#etd.dtu.dk/thesis/246031/bac09_17.pdf · Summary This report, titled "A simple aspect-oriented language based on C#" is about my work

96 BIBLIOGRAPHY

Ivar Jacobsen and Pan-Wei Ng. Aspect-Oriented Software Development withUse Cases. Addison-Wesley, 2005.

Gregor Kiczales, Erik Hilsdale, Jim Hugunin, Mik Kersten, Jeffrey Palm, andWilliam G. Griswold. An overview of aspectj. In ECOOP ’01: Proceedings ofthe 15th European Conference on Object-Oriented Programming, pages 327–353, London, UK, 2001. Springer-Verlag. ISBN 3-540-42206-4.

Jon Kleinberg and Eva Tardos. Algorithm Design. Addison-Wesley LongmanPublishing Co., Inc., Boston, MA, USA, 2005.

Donald Knuth. Frequently asked questions. URL http://www-cs-faculty.stanford.edu/~knuth/faq.html. [Online: accessed 20-June-2009].

Hanspeter Mossenbock. The Compiler Generator Coco/R - User Manual. Jo-hannes Kepler University Linz, Institute of System Software, 2006. URLhttp://www.ssw.uni-linz.ac.at/coco/Doc/UserManual.pdf. [Online; ac-cessed 21-June-2009].

Hanspeter Mossenbock, Markus Loberbauer, and Albrecht Woß. The compilergenerator coco/r, November 2008. URL http://www.ssw.uni-linz.ac.at/coco/. [Online: accessed 21-June-2009. Last updated 13-November-2008].

The AspectJ Programming Guide. Palo Alto Research Center, 2003. URL http://www.eclipse.org/aspectj/doc/released/progguide/index.html. [On-line; accessed 21-June-2009].

Lars Rosenhainer. Identifying crosscutting concerns in requirements spec-ifications. In Workshop on Early Aspects, pages 49–58, 2004. URLhttp://trese.cs.utwente.nl/workshops/oopsla-early-aspects-2004/Papers/Rosenhainer.pdf.

Bjarne Stroustrup. Bjarne stroustrup’s faq, May 2009. URL http://public.research.att.com/~bs/bs_faq.html. [Online: accessed 24-June 2009].

TIOBE. Tiobe programming community index for june 2009, June2009. URL http://www.tiobe.com/index.php/content/paperinfo/tpci/index.html. [Online: accessed 24-June-2009].

Mitchell Wand, Gregor Kiczales, and Christopher Dutchyn. A semantics foradvice and dynamic join points in aspect-oriented programming. In ACMTransactions on Programming Languages and Systems, 2002.