• No results found

Contributions

as libraries. Programmers are already accustomed to making decisions about what libraries are reasonable to depend upon. An ecosystem of language extensions allows them to make decisions about which language features are reasonable on a program- by-program basis. This frees the language standard committee from an impossible task of trying to please everyone, while giving everyone much of what they want. As we will see much later, it does not free language designers from having to design or evolve their host language, but it does focus their task. New features in the host language can enable new language extensions that might not otherwise be possible, and the standard library may wish to evolve to take advantage of new features as well.

1.4 Contributions

This thesis makes three major contributions, as well as two more minor ones that merit attention here as well.

Our chosen setting for investigating language extensions is attribute grammars [20], which are a kind of programming language well-suited to implementing compilers. At- tribute grammars with forwarding [21] offer a uniquely promising approach to com- posing together language extensions. We can take a host language implementation, and several language extension implementations for that host language and attempt to compose them in a straight-forward way. Forwarding is the key reason why we’re interested in attribute grammars specifically, everything else about attribute gram- mars has close analogs in other kinds of programming languages. (These concepts will be explained more in the background of chapter 3.) Our first minor contribution is to define (in chapter4) an attribute grammar-based programming language Ag, with a

1.4. Contributions

useful combination of language features well-suited to compiler implementation, plus the addition of a novel pattern matching semantics that does not compromise the extensibility of the language being implemented.

Although this language has useful features for implementing composable language extensions, it does not solve the problems associated with composition. For instance, it is perfectly possible to implement extensions that work in isolation, but as soon as they are composed together cause the host compiler to crash due to missing glue code. In chapter 5, we contribute a modular well-definedness analysis for Ag. This analysis, for attribute grammars with forwarding, restricts what language extensions are capable of slightly, in order to guarantee that composition of extensions will always succeed without any missing glue code. This ensures that the composed attribute grammar will be well-defined (again, a concept we will describe in chapter 3) but in a

modular way: we never examine the composed attribute grammar, only the host and

each extension in isolation. This ensures the burden of making language extensions composable falls on the extension developers and not the user who is just trying to use them.

Next, in chapter 6, we introduce the problem of interference. Although the mod- ular well-definedness analysis ensures no glue code is outright missing, there are still potentially problems. For instance, there is the question of whether the generated implicit glue code is the correct behavior in all cases. Or, we could be concerned that one extension computes values that flow into another extension where they are totally unexpected, causing misbehavior. We ensure problems of this sort are impossible, by turning the problem on its head and contributing a notion we call coherence. Coher- ence ensures that we are able to prove properties about our language extensions in a modular way, and we can compose these modular proofs and specifications success-

1.4. Contributions

fully just as we can compose the attribute grammars. In some sense, this is the same composition problem but up a level, from attribute grammars to logic, and coherence plays a similar role to forwarding and the modular well-definedness analysis. Coher- ence does have a draw back, however: in order to ensure we preserve properties, all our properties must be coherent. This is a restriction on the kinds of extensions we can write, since we are then ruling out extensions that need incoherent properties to ensure their correctness. Coherence has a major advantage, too: it turns out there are effective methods for testing for inherent incoherence in attribute grammars, without having to do any verification or proof work at all. The final result are extensions we can be confident behave as specified when composed together, and so we have ruled out interfering misbehavior.

As our final major contribution, we synthesize all this work together to imple- ment AbleC, a C compiler front-end that supports reliable composition of language extensions. This tool relies on the modular well-definedness analysis, the coherence approach to non-interference, as well as a “modular determinism analysis” for reli- ably composing syntactic extensions (this last from prior work, and introduced in section 3.3). This serves as an evaluation of these techniques, as well as a platform for further research.

As our last minor contribution, we observe that the combination of these three tools for ensuring reliable composition has interesting implications for language de- sign. First, it defines a precise space of potential extensions around a host language. Extensions within this space are all reliably composable with each other, and outside they are not permitted by this system. The extent of this space depends on the host language and its design. And so, this also serves as a tool for helping host language designers focus on what is important. Instead of only being concerned with directly